是否可以在C#中调用泛型参数的方法?

时间:2011-12-22 20:39:07

标签: c#

在C ++中,您可以从模板参数中调用方法,如下所示:

template<class T> class foo
{
  T t;
  t.foo();
}

但是在C#中,看起来这是不可能的:

class foo<T>
{
  T t;
  public void foo() { 
    t.foo(); // Generates a compiler error
  }
};

我想这可能在C#中是不可能的,是吗?

4 个答案:

答案 0 :(得分:11)

您已发现 templates generics 之间的区别。虽然它们看起来很相似但实际上却完全不同。

模板只需要对实际提供的类型参数正确;如果你提供一个没有方法foo的T,那么编译失败;如果只提供具有foo的类型参数,则编译成功。

相比之下,通用必须对任何可能的T 都是正确的。由于我们没有证据表明每个可能的T 都有方法foo,因此通用是非法的。

答案 1 :(得分:9)

是的,如果您知道泛型类型占位符T实现了基类或接口的成员,则可以使用{{1}将类型T约束到该基类或接口条款。

where

这样可以将通用类型占位符public interface IFooable { void Foo(); } // ... public class Foo<T> where T : IFooable { private T _t; // ... public void DoFoo() { _t.Foo(); // works because we constrain T to IFooable. } } 视为T。如果约束泛型中的泛型类型占位符,则它被约束为IFooable,这意味着只有object的成员对泛型可见(即,您只看到object引用可见的成员,但调用任何被覆盖的成员将调用适当的覆盖。)

注意:这是非常重要的,因为运算符重载之类的东西(记住运算符是重载的,而不是重写的)所以如果你有这样的代码:

object

即使public bool SomeSuperEqualsChecker<T>(T one, T two) { return one == two; } object,也会始终使用==的{​​{1}}。但是,如果我们有:

T

此WOULD按预期与string一起工作,因为public bool SomeSuperEqualsChecker<T>(T one, T two) { // assume proper null checking exists... return one.Equals(two); } 被覆盖,而不是重载。

因此,长和短只是记住一个不受约束的通用占位符确实代表任何类型,但唯一可见的调用和操作是string上可见的。

除了接口/基类约束之外,还有一些其他约束:

  • Equals() - 表示泛型类型占位符必须具有默认构造函数
  • object - 表示通用类型占位符必须是引用类型
  • new() - 表示泛型类型占位符必须是值类型(枚举,原语,结构等)

例如:

class

希望这有帮助。

答案 2 :(得分:3)

您需要在方法中添加type constraint

public interface IFoo {
    void Foo();
}

public class Foo<T> where T : IFoo {
     T t;  
    public void foo() {   
        t.Foo(); // Generates a compiler error  
    }
}

答案 3 :(得分:3)

如果您愿意接受泛型类型约束,则可能。这意味着必须将通用类型约束为从某个基类派生或实现某些接口。

示例:

abstract class SomeBase
{
    public abstract DoSomething();
}

// new() ensures that there is a default constructor to instantiate the class
class Foo<T> where T : SomeBase, new()
{
    T t;

    public Foo()
    {
        this.t = new T();
        this.t.DoSomething(); // allowed because T must derive from SomeBase
    }
}