使用泛型中的参数的new()约束的解决方法

时间:2014-07-22 12:05:00

标签: c# generics

我知道,SO上有一些答案,似乎可以解决我的问题,例如thisthat个主题。但在我的具体情况下,存在一些差异。

前面我的问题:这是一个可行的/智能的解决方法来管理带参数的泛型中的new()约束吗?

假设以下基类:

abstract class BaseClass
{
    internal BaseClass()
    {
        Console.WriteLine("{0}'s ctor (parameterless)", "BaseClass");
    }

    internal BaseClass(object parent)
    {
        Console.WriteLine("{0}'s ctor", "BaseClass");
        Parent = parent;
    }

    public object Parent { get; private set; }
}

和界面:

interface IGenerate
{
    IGenerate GenerateNew(int x, object parent);
}

基类只用于存储父对象,该接口提供了一个方法来返回实现类的对象,调用其构造函数,如下所示:

class ClassX : BaseClass, IGenerate
{
    public ClassX()
    {
        Console.WriteLine("{0}'s ctor (parameterless)", "ClassX");
    }

    public ClassX(int x, object parent)
        : base(parent)
    {
        Console.WriteLine("{0}'s ctor", "ClassX");
        X = x;
    }

    public IGenerate GenerateNew(int x, object parent)
    {
        Console.WriteLine("{0}.GenerateNew()", "ClassX");
        return new ClassX(x, parent);
    }

    public int X { get; private set; }
}

我的泛型类旨在生成和存储所提供的类的对象,该对象调用interfaces方法:

class MyGeneric<T> : BaseClass where T : IGenerate, new()
{
    public MyGeneric(int x, object parent)
        : base(parent)
    {
        Console.WriteLine("{0}'s ctor", "MyGeneric");
        Instance = new T().GenerateNew(x, this);
    }

    public IGenerate Instance { get; private set; }
}

另一个类继承泛型:

class ClassXSpecifier : MyGeneric<ClassX>
{
    public ClassXSpecifier(int x, object parent)
        : base(x, parent)
    {
        Console.WriteLine("{0}'s ctor", "ClassXSpecifier");
    }
}

这些结构的使用是这样的:

var classXspecifier = new ClassXSpecifier(5, null);
var classX = (ClassX)classXspecifier.Instance;
Console.WriteLine(classX.X);

输出:

BaseClass's ctor
MyGeneric's ctor
BaseClass's ctor (parameterless)
ClassX's ctor (parameterless)
ClassX.GenerateNew()
BaseClass's ctor
ClassX's ctor
ClassXSpecifier's ctor
5

这是我的主要问题:这是一个可能/智能的解决方法来管理带参数的泛型中的new()约束吗?

第二个问题:为什么BaseClassClassX需要一个无参数构造函数,而它们在任何情况下都不会被使用 明确?如果我删除它们,我会收到以下错误:

  

&#39; ClassX&#39;必须是具有公共无参数的非抽象类型   构造函数,以便将其用作参数&#39; T&#39;在通用类型或   方法&#39; MyGeneric&#39;

提前致谢,Christian =)

!!!解决方案!!!

提供的答案诱使我做出修改,可以删除new()约束 - &gt;所以也可以删除无参数构造函数。

我删除了界面并在BaseClass中添加了一个静态方法来生成新对象:

public static BaseClass GenerateNew(Type T, object[] args)
{
    return (BaseClass)Activator.CreateInstance(T, args);
}

因此泛型类可以简化为

class MyGeneric<T> : BaseClass
{
    public MyGeneric(int x, object parent)
        : base(parent)
    {
        Console.WriteLine("{0}'s ctor", "MyGeneric");
        Instance = GenerateNew(typeof(T), new[] { x, parent });
    }

    public BaseClass Instance { get; private set; }
}

就是这样,感谢所有评论!

2 个答案:

答案 0 :(得分:1)

问题
我的主要问题是:这是一个可能/智能的解决方法来管理带参数的泛型中的new()约束吗?

答案
您传递类型(ClassX)并想要在不创建实例的情况下访问实例函数(GenerateNew) - &gt;以及你需要考虑的一个问题。 您可以创建静态工厂(和\或使用IOC)来按类型创建新对象。

问题
为什么BaseClass和ClassX需要一个无参数构造函数,而它们在任何情况下都不会被明确使用?

答案
此约束要求使用的泛型类型是非抽象的,并且它具有允许您调用它的默认(无参数)构造函数。 顺便说一句,你是通过new T()来使用空的ctor。

答案 1 :(得分:1)

这不是最好的解决方案,但我当时所做的是需要一个返回泛型并提供构造函数作为函数参数的函数:

SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request /transform2 (ip <ip_address>) !!!
uwsgi_response_writev_headers_and_body_do(): Broken pipe [core/writer.c line 306] during POST /transform2 (<ip_address>)
OSError: write error
[pid: 27863|app: 0|req: 156/335] <ip_address> () {50 vars in 1083 bytes} [Mon Jul 27 02:18:38 2020] POST /transform2 => generated 0 bytes in 60835 msecs (HTTP

要调用该方法,请使用名为Foo的类作为通用类型:void<T> GenericMethod(Func<string, T> ctor) { T t = ctor("foo"); }

args不需要在调用泛型方法之前定义,仅用于指示将如何使用ctor的参数。