Подтвердить что ты не робот

Почему С# не разрешает общие свойства?

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

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

foo.Bar<Baz>=3;

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

foo.Bar<Baz> = 3;

Или:

foo.Bar < Baz >= 3;

Ответ 4

Я думаю, что использование автоматического геттера/сеттера не иллюстрирует, почему это невозможно без определения "Т" на уровне класса.

Попробуйте его кодировать, естественным делом будет следующее:

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" .

Ответ 5

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

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