为什么c#不允许泛型属性
本文关键字:属性 泛型 不允许 为什么 | 更新日期: 2023-09-27 18:18:53
我想知道为什么我不能在非泛型类中拥有泛型属性,我可以拥有泛型方法。例如:
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; }
}