开发者

using static methods of a constrained generic type C#

开发者 https://www.devze.com 2023-03-26 13:14 出处:网络
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.

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 w开发者_StackOverflow中文版ant 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?


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);
}


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.


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?


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#.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号