为什么C#不允许通用属性?

时间:2011-12-23 21:43:36

标签: c# language-design language-specifications

我想知道为什么我不能像通用方法那样在非泛型类中拥有泛型属性。即:

public interface TestClass
{
   IEnumerable<T> GetAllBy<T>(); //this works

   IEnumerable<T> All<T> { get; } //this does not work
}

我读过@Jon Skeet的answer,但这只是一个陈述,很可能是规范中的某个地方。

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

5 个答案:

答案 0 :(得分:14)

从技术上讲,CLR只支持泛型类型和方法,而不支持属性,所以问题是它没有添加到CLR中。对此的答案可能只是“它不被视为带来足够的好处,值得花费”。

但更重要的是,它被认为没有带来任何好处,因为在一个类型中对属性进行参数化在语义上没有意义。 Car类可能具有Weight属性,但拥有Weight<Fruit>Weight<Giraffe>属性毫无意义。

答案 1 :(得分:11)

Julian Bucknall的这篇Generic Properties 博客文章是一个很好的解释。基本上这是一个堆分配问题。

答案 2 :(得分:2)

我的猜测是,它有一些令人讨厌的角落案例,使语法模棱两可。副手,这似乎有点棘手:

foo.Bar<Baz>=3;

应该将其解析为:

foo.Bar<Baz> = 3;

或者:

foo.Bar < Baz >= 3;

答案 3 :(得分:0)

我认为不使用自动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”将是什么。

答案 4 :(得分:-1)

我做了那样的事。 它在运行时键入检查。

{
  "size": 0,
  "aggs": {
    "autocomplete": {
      "terms": {
        "field": "autocomplete",
        "include": {
          "pattern": "fabulo(.*)"
        }
      }
    }
  },
  "query": {
    "prefix": {
      "autocomplete": {
        "value": "fabulo"
      }
    }
  }
}