Fernando Torres
Fernando Torres

Reputation: 1180

How do I make the return OBJECT of a method generic?

I need to do somthing like below code, but new T() does not work. It says "Cannot create an instance of variable type T because it does not have a new() constraint."

public static T MapToBaseDropDown2<T>(this GenericDropDownData dd) where T : BaseDropDown
{
    return new T() //FAILS
    {
        Id = dd.Id,
        Description = dd.Description
    };
}

BaseDropDown is the base class for 3 childs that are entities mapped with EntityFramework (code first), so it may be better keep it as simple as possible.

Now it is not abstract due to some implementations that I tried, but if possible it will be.

public class BaseDropDown
{
    public int Id { get; set; }
    public string Description { get; set; }
}

Upvotes: 2

Views: 179

Answers (4)

Fernando Torres
Fernando Torres

Reputation: 1180

This also works, just adding the new() constraint directly to T (not to BaseDropDown)

public static T MapToBaseDropDown3<T>(this GenericDropDownData dd) where T : BaseDropDown, new()
{
    return new T()
    {
        Id = dd.Id,
        Description = dd.Description
    };
}

Upvotes: 2

MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37000

Calling new T() assumes that every type has a parameterless-constructor, which doesn´t seem to be the case here. Even if your base-class BaseDropDown has such a constructor that isn´t guranteed for all its subclasses, in particular abstract ones:

class BaseDropDown
{
    public BaseDropDown() { /* see parameterless-constructor exists */ }
}
abstract class MyClass : BaseDropDown
{
    public MyClass() { ... }
}

Now you could use the new-constraint to exclude abstract classes:

public static T MapToBaseDropDown2<T>(this GenericDropDownData dd) where T : BaseDropDown, new()

That constraint will onlx allow classes that inherit BaseDropDown and are instantiable using a parameterless constructor.

Upvotes: 2

Fernando Torres
Fernando Torres

Reputation: 1180

Using reflection works fine:

public static T MapToBaseDropDown2<T>(this GenericDropDownData dd) where T : BaseDropDown
{
    T entityDd = (T)Activator.CreateInstance(typeof(T));
    entityDd.Id = dd.Id;
    entityDd.Description = dd.Description;
    return entityDd;
}

Upvotes: -1

Stephen Wilson
Stephen Wilson

Reputation: 1514

The BaseDropDown class needs to have the new() constraint applied like this:

public class BaseDropDown<T> where T : SomeClass, new()
{
}

The new() constraint must always be applied last. See here for more details.

Upvotes: 1

Related Questions