2

i'm not sure even it's possible but here the problem i'm trying to add item to List<T> as follow

public static SelectList  ToSelectList<T>(List<T> addlist) where T : new ()
{
    addlist.Insert(0, new T { Id = -1, Name = "SELECT" });
    var list = new SelectList(addlist, "Id", "Name");
    return list;                
}

new T { Id = -1, Name = "SELECT" } throwing error is it possible to add item to List<T>?

sujith karivelil
  • 28,671
  • 6
  • 55
  • 88
Gayan
  • 2,750
  • 5
  • 47
  • 88
  • 2
    How do you expect it to work? There are classes in this world which do not have `Id` and `Name` properties. What if `T` is `System.IO.Stream`, then what is it expected to do ? – Yeldar Kurmangaliyev Aug 02 '17 at 05:09
  • Your code further constrains T in that it requires properties Id and Name. – StuartLC Aug 02 '17 at 05:10
  • those instance i pass do have Id and Name i'm not sure to use for all classes, so let's say i do have base class with those two properties – Gayan Aug 02 '17 at 05:10
  • @GayanRanasinghe You can create an interface like `INamedEntity` with `Id` and `Name` properties and add `where T : INamedEntity, new()` constraint. – Yeldar Kurmangaliyev Aug 02 '17 at 05:11
  • you should use polymorphism, i.e use constraint to base class where all classes with Id and Name inheriting that base class. – M.kazem Akhgary Aug 02 '17 at 05:12
  • you should declare Interface type with Id and name of the T. that way only you should access the properties. and assign the values – umasankar Aug 02 '17 at 05:13
  • thanks umasanka, M.kazem Akhgary , Yeldar Kurmangaliyev, StuartLC and this is for those who minus voted if i do have proper explanation i never post here for the help if you do not have solution it doesn't mean question should get minus vote. thanks – Gayan Aug 02 '17 at 05:16
  • 2
    I upvoted to balance out whoever downvoted your question. I honestly don't know what the downvote is for. – Devin L. Aug 02 '17 at 05:39

2 Answers2

3

The problem is that, via the generic constraints, you have declared T as any object with a default constructor.

The compiler performs type checking at compile time, and T does not neccessarily have the properties Id or Name.

A solution is to

  • Create an interface which does have Id and Name,
  • Modify every compatible class so it implements this interface.
  • Add another generic constraint to your function, requiring the type parameter to implement this interface.

A compiling example:

public interface IEntity
{
    int Id {get; set; }
    string Name {get; set; }
}

class Widget : IEntity 
{
    public int Id {get; set; }
    public string Name {get; set; }    

    public string SomeOtherProperty { get; set; }
}

public static SelectList  ToSelectList<T>(List<T> addlist) where T : IEntity, new ()
{
    addlist.Insert(0, new T { Id = -1, Name = "SELECT" });
    var list = new SelectList(addlist, "Id", "Name");
    return list;

}

// In your code
List<Widget> widgetList = new List<Widget>();
ToSelectList(widgetList);
Andrew Shepherd
  • 44,254
  • 30
  • 139
  • 205
2

The problem with your code is that you do not know what T is and what properties it has. new is not enough as your generic constraint. All it specifies it:

The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor

If you want to go and just instantiate an object of type T then see: Create instance of generic type?.

But what might be better is just to create an interface with those properties, specify that your function gets a list of that type and then just instantiate an object of that type:

public static SelectList ToSelectList(List<YourInterface> addlist)
{
    addlist.Insert(0, new YourDerived { Id = -1, Name = "SELECT" });
    var list = new SelectList(addlist, "Id", "Name");
    return list;    
}
Gilad Green
  • 36,708
  • 7
  • 61
  • 95