如何使通用方法的返回OBJECT?

问题描述:

我需要做财产以后像下面的代码,但新T()不工作。它说 “因为它不具有new()约束无法创建变量类型T的实例。”如何使通用方法的返回OBJECT?

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

BaseDropDown为3名儿童的能与的EntityFramework(代码第一)映射实体的基类,所以它可能是更好保持尽可能的简单。

现在它不是抽象的,由于一些实现,我试过了,但如果可能的话会。

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

谷歌 “新约束” - 找到答案:https://docs.microsoft.com/en-us/ dotnet/csharp/language-reference/keywords/new-constraint – Chris

+0

什么是'BaseDropDown'?显示它如何定义。 – HimBromBeere

+1

这是因为您的扩展方法可能适用于没有构造函数的类,非公共构造函数或具有必需参数的构造函数。使用'new()'约束,你可以确定使用你的方法的实例有一个没有任何参数的公共构造函数。 – 0xaryan

这也适用,只需直接添加new()约束T(不BaseDropDown)

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

BaseDropDown类需要应用这样的new()约束:

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

new()约束必须始终是最后一个应用。有关更多详情,请参阅here

+1

'BaseDropDown'似乎不是通用的,但是'MapToBaseDropDown2'是。 – HimBromBeere

使用反射正常工作:

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

你应该使用'新()'约束,而不是这种技术。这样,如果你尝试用缺少无参数构造函数的'T'来执行此操作,它将在**编译**时失败。你的代码可以很好地编译,但是在**运行时会失败。 – mjwills

+0

你是对的,谢谢 –

调用new T()假定每个类型无参数的构造函数,这doesn't似乎是这里的情况。即使你的基类BaseDropDown有这样isn't存在保证其所有子类,特别是那些抽象构造函数:

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

现在你可以使用new -constraint到排除抽象类:

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

这约束将onlx允许继承BaseDropDown使用参数的构造函数是实例化类。