为什么 C# 不允许泛型属性?

发布于 2024-12-22 11:48:55 字数 368 浏览 3 评论 0原文

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

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

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

我阅读了 @Jon Skeet 的答案,但这只是一个声明,很可能位于规范中的某个位置。

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

I was wondering why I can not have generic property in non-generic class the way I can have generic methods. I.e.:

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

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

I read @Jon Skeet's answer, but it's just a statement, which most probably is somewhere in the specifications.

My question is why actually it is that way? Was kind of problems were avoided with this limitation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

锦上情书 2024-12-29 11:48:55

从技术上讲,CLR 仅支持泛型类型和方法,而不支持属性,因此问题是为什么它没有添加到 CLR 中。答案可能很简单:“它没有被认为带来足够的好处,值得付出的代价”。

但更根本的是,它被认为不会带来任何好处,因为通过类型参数化属性在语义上没有意义。 Car 类可能具有 Weight 属性,但拥有 WeightWeight是没有意义的; 属性。

Technically, the CLR supports only generic types and methods, not properties, so the question is why it wasn’t added to the CLR. The answer to that is probably simply “it wasn’t deemed to bring enough benefit to be worth the costs”.

But more fundamentally, it was deemed to bring no benefit because it doesn’t make sense semantically to have a property parameterised by a type. A Car class might have a Weight property, but it makes no sense to have a Weight<Fruit> and a Weight<Giraffe> property.

柠栀 2024-12-29 11:48:55

Julian Bucknall 的这篇通用属性博客文章提供了很好的解释。本质上这是一个堆分配问题。

This Generic Properties blog post from Julian Bucknall is a pretty good explanation. Essentially it's a heap allocation problem.

岁月静好 2024-12-29 11:48:55

我的猜测是,它有一些令人讨厌的极端情况,导致语法含糊不清。副手,这似乎可能很棘手:

foo.Bar<Baz>=3;

应该解析为:

foo.Bar<Baz> = 3;

或者:

foo.Bar < Baz >= 3;

My guess is that it has some nasty corner cases that make the grammar ambiguous. Off-hand, this seems like it might be tricky:

foo.Bar<Baz>=3;

Should that be parsed as:

foo.Bar<Baz> = 3;

Or:

foo.Bar < Baz >= 3;
十六岁半 2024-12-29 11:48:55

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

I think not using an automatic getter/setter illustrates why this isn't possible without having "T" defined at the class level.

Try coding it, the natural thing to do would be this:

IEnumerable<T> _all;
IEnumerable<T> All
{
    get { return _all; }
}

Because your field uses "T", then "T" needs to be on the class the CLR knows what "T" is.

When you're using a method, you can delay definition of "T" until you actually call the method. But with the field/property, "T" needs to be declared in one place, at the class level.

Once you declare T on the class, creating a property becomes pretty easy.

public class TestClass<T>
{
    IEnumerable<T> All { get; }
}

usage:

var myTestClass = new TestClass<string>();
var stuff = myTestClass.All;

And just like the "T" type parameter on a method, you can wait until you actually instantiate your TestClass to define what "T" will be.

心在旅行 2024-12-29 11:48:55

我做了类似的东西。
它在运行时进行类型检查。

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; }
}

I made somthing like that.
It type checks at run time.

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; }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文