2016-11-14 2 views
0

Должно быть relativly простой, но я не могу понять это, я бы следующее:Как добавить элементы универсального типа в список?

public static List<T> GetList <T>(dynamic data) 
    { 
     var lst = new List<T>(); 

     foreach (var d in data) 
     { 
      lst.Add(new T { Value = d.Id.ToString(), Text = d.Name };); 
     } 

     return lst; 
    } 

errror:

enter image description here

+0

Почему бы не использовать интерфейсы? – JuanR

+1

у вас нет ограничений на 'T'.Компилятор не знает, что 'T' имеет свойство« Значение »или« Текст ». – Jonesopolis

+0

Вы ограничили свой тип T, но не предоставили никаких дополнительных ограничений для этого типа. Компилятор не может знать, что существует свойство Value или Text. – Igor

ответ

7

Вы ограничили свой тип T, но не предоставляли никаких дополнительных ограничений для этого типа. Компилятор не может знать, что существует свойство Value или Text. Вы можете использовать интерфейс, а затем ограничить его. Тип, который вы передаете, когда вы вызываете метод, должен также реализовать этот интерфейс.

public interface ITextValue{ 
    string Text {get;set;} 
    string Value {get;set;} 
} 

А затем код с дополнительным ограничением

public static List<T> GetList <T>(dynamic data) where T : ITextValue, new() 
{ 
    var lst = new List<T>(); 

    foreach (var d in data) 
    { 
     lst.Add(new T { Value = d.Id.ToString(), Text = d.Name }); 
    } 

    return lst; 
} 

Вот хорошая ссылка на все имеющиеся ограничения и синтаксис для тех ограничений, которые могут быть применены к параметрам универсального типа. Constraints on Type Parameters (C# Programming Guide). И вместе с тем, что @juan указал, что ограничение new() указывает, что тип, который вы используете, должен иметь конструктор без параметров.

+2

Я только что узнал что-то новое, спасибо, это сделало трюк – ThunD3eR

+1

Одна вещь, которую я хотел бы добавить, что я думаю, что @Igor забыл это новое ограничение(). Он сообщает компилятору, что T имеет открытый конструктор без параметров (это то, что позволяет вам делать новые T {}). – JuanR

+1

Еще одна вещь. Если возможно, я бы избегал использовать динамический, поскольку он пропускает проверку времени компиляции. Вместо этого вы могли бы использовать классы, которые вы передаете этому методу, реализовать интерфейс, описанный @Igor. – JuanR

0

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

Где TypeName - это тип, содержащий значение и текст.

public static List<T> GetList <T>(dynamic data) where T : TypeName, new() 
    { 
    var lst = new List<T>(); 

    foreach (var d in data) 
    { 
     lst.Add(new T { Value = d.Id.ToString(), Text = d.Name };); 
    } 

    return lst; 
    } 
+4

Это не сработает. Он все равно взорвется, потому что компилятор не знает, что T имеет свойства Value и Text или какой тип они есть. – JuanR

+0

Да, я только что понял это и добавил примечание – cstopher

+0

проголосовать за редактирование, это тоже помогло – ThunD3eR

1

С помощью генераторов C# вы можете выполнять эти операции только в экземпляре аргумента общего типа, который, как известно, компилятору существует в любом типе, который соответствует ограничениям общего типа, указанным соответствующим общим типом или общим методом , Другими словами, в вашем конкретном случае у компилятора есть две проблемы.

Сначала вы пытаетесь построить экземпляр T, хотя не каждый тип может быть построен таким образом (например, делегаты не могут). Более того, не каждый конструктор имеет тип по умолчанию-конструктив (другими словами, имеет конструктор по умолчанию). Для того, чтобы иметь возможность построить экземпляр типа T, как это, вы должны требовать T иметь конструктор по умолчанию будет применение новый() ограничение на Т.

Во-вторых, чтобы иметь возможность инициализировать свойства Значение и Текст на вновь созданный экземпляр T, вы должны быть уверены, что тип T задает такие свойства, и эти свойства: public и устанавливаемый, что обычно делается путем принудительного применения T для реализации определенного интерфейса.

Вот небольшой пример того, что вы, вероятно, захотите сделать в коде.

interface IHasStringValueAndText { 
    String Value { get; set; } 
    String Text { get; set; } 
} 

public static List<T> GetList<T>(dynamic data) where T : IHasStringValueAndText, new() { 
    var lst = new List<T>(); 

    foreach (var d in data) { 
     lst.Add(new T { Value = d.Id.ToString(), Text = d.Name }); 
    } 

    return lst; 
} 

Пожалуйста, обратите внимание, что если вы на самом деле не нужны класса ограничение для вашего конкретного случая, чтобы работать, но это может оказаться полезным в дальнейшей работе.

Смежные вопросы