C# 使用new()约束将抽象类型和面作为泛型类型参数存在问题

C# 使用new()约束将抽象类型和面作为泛型类型参数存在问题,c#,generics,constraints,C#,Generics,Constraints,我需要将泛型类型参数作为接口,但是我希望在泛型类(SomeGenericType)中实例化该类型,如下所示: class Program { static void Main(string[] args) { var val = new SomeGenericType<ISomeInterface>(); Console.ReadKey(); } } internal class SomeGenericType<T&g

我需要将泛型类型参数作为接口,但是我希望在泛型类(SomeGenericType)中实例化该类型,如下所示:

class Program
{
    static void Main(string[] args)
    {
        var val = new SomeGenericType<ISomeInterface>();

        Console.ReadKey();
    }
}

internal class SomeGenericType<T> where T : new()
{
    public SomeGenericType()
    {
        var test = new T();  
    }
}

public class SomeClass : ISomeInterface
{
    public string TestVal { get; set; }
}

public interface ISomeInterface
{
    string TestVal { get; set; }
}
类程序
{
静态void Main(字符串[]参数)
{
var val=新的SomeGenericType();
Console.ReadKey();
}
}
内部类SomeGenericType,其中T:new()
{
公共SomeGenericType()
{
var测试=新的T();
}
}
公共类SomeClass:接口
{
公共字符串TestVal{get;set;}
}
公共接口
{
字符串TestVal{get;set;}
}
这会引发以下编译时错误:

“ISomeInterface必须是具有公共无参数构造函数的非抽象类型,才能将其用作泛型类型或方法SomeGenericType中的参数“T”

我理解为什么会发生这种情况,但我想知道是否有办法解决这个问题

谢谢。

否,
new()
约束要求可以使用以下语法创建该类型的实例

new T()
无论是抽象类还是接口,这显然都不是真的,只有带有公共无参数构造函数的具体类

您可以通过删除约束并使用以下命令将问题推迟到运行时:

Activator.CreateInstance<T>()
Activator.CreateInstance()
而是创建对象。然后,只要运行时使用的实际类型满足这些约束,您的代码就会按您所希望的方式工作。但是,如果确实尝试使用接口或抽象类,则会遇到运行时错误

在您的特定情况下,此行将引发异常

var val = Activator.CreateInstance<SomeGenericType<ISomeInterface>>();
var val=Activator.CreateInstance();

您已经通过了编译时错误,但没有任何效果。

这里的问题是
新的
约束与具体的类型实现有关。这永远不能与简单的和接口或抽象类一起工作,因为它们不能直接实例化。您必须在这里提供一个具体的类

var val = new SomeGenericType<SomeClass>()
var val=new SomeGenericType()

另一种想法,可能与此无关,但看起来您正在寻找一种方法来请求一个
接口,并提供了其“默认”实现的实例
SomeClass
。这是控制反转(InversionofControl,IOC)容器可以为您处理的事情。如果您想进一步研究,可以查看Spring.NET、Microsoft Unity、AutoFac、LinFu或其他许多框架。

问题是,编译器无法知道为给定接口实例化哪个类。正如David M所指出的:

这是控制反转(InversionofControl,IOC)容器可以为您处理的事情

我认为,对于这个简单的需求来说,使用一个框架可能过于致命。您可以创建自己的
工厂
类,如下所示:

public class Factory
{
  Dictionary<Type, Type> typeMapping = new Dictionary<Type, Type>();

  public void Register<IType, CType>()
  {
    typeMapping.Add(typeof(IType),typeof(CType));
  }

  public IType Create<IType>()
  {
    Activator.CreateInstance(typeMapping[typeof(IType)]);
  }
}
公共类工厂
{
字典类型映射=新字典();
公开作废登记册()
{
添加(typeof(IType),typeof(CType));
}
公共IType创建()
{
Activator.CreateInstance(typeMapping[typeof(IType)]);
}
}

加入一些健全性检查,这个类就可以使用了。

添加额外的约束会有帮助吗<代码>其中T:ISomeInterface,new()
。正如您所提到的,您需要为泛型提供一个具体的实现,因为没有其他方法可以保证
new()
约束。如果您有Interface1,Class1:Interface1,Class2:Interface1,编译器应该如何猜测您是要创建Class1还是Class2的实例?