为什么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的回答,但它只是一个声明,很可能在规范的某个地方。

我的问题是为什么实际上是这样的?这种限制是否避免了一些问题?

为什么c#不允许泛型属性

从技术上讲,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; }
}