質問

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?

役に立ちましたか?

解決

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.

他のヒント

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

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;

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.

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; }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top