我想知道为什么我不能像通用方法那样在非泛型类中拥有泛型属性。即:
public interface TestClass
{
IEnumerable<T> GetAllBy<T>(); //this works
IEnumerable<T> All<T> { get; } //this does not work
}
我读过@Jon Skeet的answer,但这只是一个陈述,很可能是规范中的某个地方。
我的问题是为什么它实际上是这样的?这种限制是否避免了一些问题?
答案 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"
}
}
}
}