我想知道为什么我不能像拥有泛型方法那样在非泛型类中拥有泛型属性。IE:
public interface TestClass
{
IEnumerable<T> GetAllBy<T>(); //this works
IEnumerable<T> All<T> { get; } //this does not work
}
我读了@Jon Skeet 的答案,但这只是一个声明,很可能在规范中的某个地方。
我的问题是为什么实际上是这样的?这种限制是否避免了一些问题?
我想知道为什么我不能像拥有泛型方法那样在非泛型类中拥有泛型属性。IE:
public interface TestClass
{
IEnumerable<T> GetAllBy<T>(); //this works
IEnumerable<T> All<T> { get; } //this does not work
}
我读了@Jon Skeet 的答案,但这只是一个声明,很可能在规范中的某个地方。
我的问题是为什么实际上是这样的?这种限制是否避免了一些问题?
从技术上讲,CLR 只支持泛型类型和方法,而不支持属性,所以问题是为什么它没有被添加到 CLR。对此的答案可能很简单,“它被认为没有带来足够的收益来值得付出代价”。
但更根本的是,它被认为没有带来任何好处,因为将属性参数化为类型在语义上没有意义。一个Car
类可能有一个Weight
属性,但是拥有一个Weight<Fruit>
和一个Weight<Giraffe>
属性是没有意义的。
这篇来自 Julian Bucknall 的Generic Properties博客文章是一个很好的解释。本质上这是一个堆分配问题。
我的猜测是它有一些令人讨厌的极端情况,使语法模棱两可。副手,这似乎很棘手:
foo.Bar<Baz>=3;
应该将其解析为:
foo.Bar<Baz> = 3;
或者:
foo.Bar < Baz >= 3;
我认为不使用自动 getter/setter 说明了为什么如果没有在类级别定义“T”是不可能的。
尝试对其进行编码,很自然的事情是这样的:
IEnumerable<T> _all;
IEnumerable<T> All
{
get { return _all; }
}
因为您的字段使用“T”,所以“T”需要在 CLR 知道“T”是什么的类上。
当您使用方法时,您可以延迟“T”的定义,直到您实际调用该方法。但是对于字段/属性,“T”需要在类级别的一个地方声明。
一旦在类上声明了 T,创建属性就变得非常容易。
public class TestClass<T>
{
IEnumerable<T> All { get; }
}
用法:
var myTestClass = new TestClass<string>();
var stuff = myTestClass.All;
就像方法上的“T”类型参数一样,您可以等到您实际实例化您的 TestClass 来定义“T”将是什么。
我做了类似的东西。它在运行时键入检查。
public class DataPackage
{
private dynamic _list;
public List<T> GetList<T>()
{
return (List<T>)_list;
}
public void SetList<T>(List<T> list)
{
_list = list;
}
public string Name { get; set; }
}