使用受约束泛型类型 C# 的静态方法

发布于 2024-11-28 06:41:52 字数 307 浏览 1 评论 0原文

我有一个泛型类:

public class Foo<T> where T: Interface
{

}

T 被迫实现的接口在其内部定义了 2 个静态方法。

在构造函数中,我希望能够基本上执行以下操作:

public Foo()
{
   value1 = T.staticmethod1();
   value2 = T.staticmethod2();
}

这无法使用我上面发布的伪代码来完成。难道这样就不能调用这些静态方法了吗?

I have a generic class:

public class Foo<T> where T: Interface
{

}

the interface that T is being forced to implement has 2 static methods defined inside of it.

in the constructor I want to be able to basically do the following:

public Foo()
{
   value1 = T.staticmethod1();
   value2 = T.staticmethod2();
}

This cannot be accomplished with the psuedocode I have posted above. Is it not possible to call these static methods in this way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

爱格式化 2024-12-05 06:41:52

您也许可以使用扩展方法。该技术被命名为pseudo-mixins
尽管扩展方法实际上是静态的,但它们“假装”为实例方法,因此您仍然需要 T 的具体实例。

此外,如果您希望接口保留其作为自文档“契约”的角色,那么这就是一种作弊" 指定你的 T 类应该有哪些方法。
然而它们是类型安全的(如果你没有将 IBarExtensions 引入范围内,你的 Foo 类将无法编译

//our interface
public interface IBar {}

// the two static methods are define as extension methods
public static class IBarExtensions {
    public static string someMethod1(this IBar self) {
        return "my initialization 1";
    }
    public static string someMethod2(this IBar self) {
        return "my initialization 2";
    }
}

public class Foo<T> where T : IBar, new()
{
    public string value1 {get; private set;}
    public string value2 {get; private set;}

    public Foo() {
        T t = new T(); // we can do this because of the "new()" constraint
                           // in the class definition
                           // Alternatively we could pass an instance of T in
                           // the constructor 
                           // public Foo(T t)
        value1 = t.someMethod1();
        value2 = t.someMethod2();       
    }
}

public class TestBar : IBar {}
void Main()
{
    var c = new TestBar();

    var t = new Foo<TestBar>();
    Console.WriteLine(t.value1);
}

You may be able to use extension methods. This technique has been named pseudo-mixins.
Although the extension methods are actually static they "pretend" to be instance methods, so you still need a concrete instance of T.

Also, this is kind of cheating, if you want your interface to preserve its role as a self-documenting "contract" that specifies what methods your T class should have.
However they are type-safe (your Foo class will not compile, if you don't bring the IBarExtensions in scope)

//our interface
public interface IBar {}

// the two static methods are define as extension methods
public static class IBarExtensions {
    public static string someMethod1(this IBar self) {
        return "my initialization 1";
    }
    public static string someMethod2(this IBar self) {
        return "my initialization 2";
    }
}

public class Foo<T> where T : IBar, new()
{
    public string value1 {get; private set;}
    public string value2 {get; private set;}

    public Foo() {
        T t = new T(); // we can do this because of the "new()" constraint
                           // in the class definition
                           // Alternatively we could pass an instance of T in
                           // the constructor 
                           // public Foo(T t)
        value1 = t.someMethod1();
        value2 = t.someMethod2();       
    }
}

testing

public class TestBar : IBar {}
void Main()
{
    var c = new TestBar();

    var t = new Foo<TestBar>();
    Console.WriteLine(t.value1);
}
送舟行 2024-12-05 06:41:52

不,这是不可能的。即使使用动态也不行。有一些通用约束(例如接口),但仅适用于实例成员。您可以考虑将这些方法作为 Func/Action 委托传递到(参数)中?

除此之外,你唯一的(也是不受欢迎的)选择就是反思。或者也许更好:重新思考我们的方法。

No, it is not possible. Not even with dynamic. There are generic constraints (such as interfaces), but that applies to instance members only. You could consider passing those methods in (parameters) as Func<T>/Action<T> delegates?

Beyond that, your only (and undesirable) option is reflection. Or perhaps better: rethink our approach here.

嗼ふ静 2024-12-05 06:41:52

不可能使用受约束的泛型类型参数的静态成员,因为特定类型中静态成员的存在并不能说明派生类型是否具有与该名称兼容的成员。假设类型“Foo”有一个返回 Int32 的静态函数 Wowzo(),类型 DerivedFoo1 有一个不同的静态函数 Wowzo(),它也返回 Int32,类型 DerivedFoo2(派生自 Foo)有一个静态成员 Wowzo()返回一个 String,并且类型 DerivedFoo3 有一个名为 Wowzo 的嵌套类。如果 T 是一个类型参数,被限制为 Foo 的后代,那么 T.Wowzo 是什么?

It is not possible to use static members of constrained generic type parameters, because the existence of a static member in a particular type says nothing about whether a derived type will have a compatible member with that name. Suppose that type "Foo" has a static function Wowzo() that returns an Int32, type DerivedFoo1 has a different static function Wowzo() that also returns an Int32, type DerivedFoo2 (which derives from Foo), has a static member Wowzo() that returns a String, and type DerivedFoo3 has a nested class called Wowzo. If T is a type parameter constrained to be a descendant of Foo, what is T.Wowzo?

陈年往事 2024-12-05 06:41:52

C# 不允许调用接口中定义的静态方法。它发出命名不当错误消息:

如果您使用以允许接口中的静态成员的语言编写的库,并且您尝试从 C# 访问静态成员,也会发生 CS0017。

如果 C# 允许,您将使用接口名称而不是通用参数名称来调用它们:

// doesn't work:
public Foo() {
  value1 = Interface.staticmethod1();
  value2 = Interface.staticmethod2(); 
} 

因此,您有几个选择:

  1. 使用允许调用这些成员的语言(我认为) em> VB.NET 和 C++/CLI 允许这样做)。您可以编写一个可以在 C# 中使用的小型适配垫片;
  2. 要求为您提供此接口的人(也许甚至是您)不要在接口中使用静态成员。它们可以移动到单独的静态类中。该类甚至可以嵌套在接口中(如果语言允许的话),并且它将在 C# 中工作。

C# doesn't allow you to call static methods defined in interfaces. It issues a poorly named error message:

CS0017 also occurs if you use a library written in a language that allows static members in interfaces, and you try to access the static member from C#.

If C# would allow it, you'd use the interface name, and not the generic parameter name, to call them:

// doesn't work:
public Foo() {
  value1 = Interface.staticmethod1();
  value2 = Interface.staticmethod2(); 
} 

So, you have a couple of options:

  1. Use a language that allows calling these members (I think VB.NET and C++/CLI allow this). You can write a small adaptation shim that you can use from C#;
  2. Ask the people who provided you this interface (maybe it's even you) to not use static members in interfaces. They can be moved to separate static classes. The class can even be nested in the interface (if the language allows it), and it will work from C#.
听你说爱我 2024-12-05 06:41:52

您还可以使用非静态方法作为调用静态方法的包装器。然后,非静态方法可以成为接口的一部分。

You could also have a non static method as a wrapper calling your static method. The non static method can then be part of your interface.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文