c#为什么不能打开泛型类型作为参数传递?

时间:2012-03-20 22:46:15

标签: c# generics

为什么无法打开泛型类型作为参数传递。我经常上课:

public class Example<T> where T: BaseClass
{
   public int a {get; set;}
   public List<T> mylist {get; set;}
}

让我们说BaseClass如下;

public BaseClass
{
    public int num;
}

然后我想要一种说法的方法:

public int MyArbitarySumMethod(Example example)//This won't compile Example not closed
{
   int sum = 0;
   foreach(BaseClass i in example.myList)//myList being infered as an IEnumerable
       sum += i.num;
   sum = sum * example.a;
   return sum;
}

然后我必须编写一个接口,只是为了将这一个类作为参数传递,如下所示:

public interface IExample
{
public int a {get; set;}
public IEnumerable<BaseClass> myIEnum {get;}
}

然后必须将泛型类修改为:

public class Example<T>: IExample where T: BaseClass
{
   public int a {get; set;}
   public List<T> mylist {get; set;}
   public IEnumerable<BaseClass> myIEnum {get {return myList;} }
}

对于我认为编译器可以推断的内容,这是很多仪式。即使某些事情无法改变,如果我知道缺少Syntax捷径的原因/理由,我发现它在心理上非常有帮助。

3 个答案:

答案 0 :(得分:2)

我一直处于类似情况,但我从来没有这个(非常好!)的问题。现在我不得不考虑一下,这是我的答案:

您希望以下内容有效:

void F(Example<> e) {
   Console.WriteLine(e.a); //could work
}

是的,理论上这可行,但这不会:

void F(Example<> e) {
   Console.WriteLine(e.mylist); //?? type unknown
}

您希望编译器和CLR能够分析方法体并证明在第一种情况下确实不存在不安全的访问。那可以成功。为什么不呢?可能,设计并不是真的很混乱。此外,“默认情况下,所有功能都未实现。有人必须实施,测试和记录它们。”

编辑:我想指出,如果没有CLR的合作,这个功能就无法实现。 C#编译器必须发出要调用的确切方法,这在开放泛型类型中是不可能的。类型系统现在甚至不允许这样的变量。

答案 1 :(得分:2)

一个实现原理:支持这将要求所有非私有泛型类方法都是虚拟的,否则将无法知道调用哪个特定方法来实现“开放”泛型类型。不同的闭合类型方法有不同的jitting,具有不同的对应方法指针。手动定义接口对应于指示编译器必须将哪些方法视为虚拟,并且还允许您准确指定要公开的“打开”功能的哪个子集。您提议的基本上是所有泛型类都有一个为其公共接口的“开放”部分隐式生成的接口类,即使从未使用过此功能,也会对该类产生性能影响。

答案 2 :(得分:1)

也许我不理解您的确切问题,但您可以通过声明这样的方式让您的“MyArbitrarySumMethod”采取任意示例:

public int MyArbitarySumMethod<T>(Example<T> example) where T : BaseClass

然后您可以在不指定“T”的情况下调用它:

int sum = MyArbitrarySumMethod(myExampleInstance);

这就是你要找的东西吗?