Почему C # не допускает общих свойств? - PullRequest
26 голосов
/ 24 декабря 2011

Мне было интересно, почему у меня не может быть универсального свойства в неуниверсальном классе, как у меня могут быть универсальные методы. I.e.:

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

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

Я прочитал ответ @Jon Skeet , но это всего лишь утверждение, которое, скорее всего, где-то в спецификациях.

Мой вопрос: почему на самом деле это так? Были ли устранены проблемы с этим ограничением?

Ответы [ 5 ]

14 голосов
/ 24 декабря 2011

Технически, CLR поддерживает только общие типы и методы, а не свойства, поэтому вопрос заключается в том, почему он не был добавлен в CLR. Ответ на этот вопрос, вероятно, просто «он не принес достаточной выгоды, чтобы стоить затрат».

Но, что более важно, считалось, что это не приносит никакой пользы, потому что семантически не имеет смысла иметь свойство, параметризованное типом. Класс Car может иметь свойство Weight, но нет смысла иметь свойство Weight<Fruit> и Weight<Giraffe>.

11 голосов
/ 24 декабря 2011

Это Общие свойства сообщение в блоге Джулиана Бакнолла - довольно хорошее объяснение.По сути, это проблема выделения кучи.

2 голосов
/ 06 января 2012

Я предполагаю, что у него есть несколько неприятных угловых случаев, которые делают грамматику неоднозначной. Вне руки это может показаться сложным:

foo.Bar<Baz>=3;

Должно ли это быть проанализировано как:

foo.Bar<Baz> = 3;

Или:

foo.Bar < Baz >= 3;
0 голосов
/ 29 марта 2017

Я сделал что-то подобное.Это тип проверки во время выполнения.

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; }
}
0 голосов
/ 24 декабря 2011

Я думаю, что не использование автоматического метода получения / установки показывает, почему это невозможно без определения "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».

...