实例化类的通用字段

时间:2016-05-06 18:20:36

标签: c# .net generics constructor field

有没有办法让类中的泛型字段专门用于构造函数中的特定类型?

例如:

class concreteClass1
{
    private int a;
    public concreteClass1( int a)
    {
        this.a = a;
    }
}

class concreteClass2
{
    string b;
    public concreteClass2(string b)
    {
        this.b = b;
    }
}

class A<T>
{
    private T field;
    public A(int x)
    {
        field = new concreteClass1(x); //error here CS0029
    }

    public A(string y)
    {
        field = new concreteClass2(y); //error here CS0029
    }
}

因此T可以是concreteClass1concreteClass1,他们各自的ctors将有不同的签名。

2 个答案:

答案 0 :(得分:1)

由于必须转换类型,这有点棘手。也许这对你有用吗?

class Program
{
    static void Main(string[] args)
    {
        var myImplementation = new Implementation<int>(4);
        var myImplementation2 = new Implementation<string>("Hello World");

        Console.WriteLine(myImplementation.myConcreteField); // outputs 4!
        Console.WriteLine(myImplementation2.myConcreteField); // outputs Hello World
    }
}

abstract class MyAbstract<T>
{
    public T MySomething;
    public MyAbstract(T something)
    {
        MySomething = something;
    }
}

class ConcreteA<T> : MyAbstract<T>
{
    public ConcreteA(int something) : base((T)Convert.ChangeType(something, typeof(T)))
    {
    }
}

class ConcreteB<T> : MyAbstract<T>
{
    public ConcreteB(string something) : base((T)Convert.ChangeType(something, typeof(T)))
    {
    }
}

class Implementation<T>
{
    public MyAbstract<T> myConcreteField;

    public Implementation(T a)
    {
        myConcreteField = new ConcreteA<T>(4);
    }

    void DoSomething()
    {
        Console.Write(myConcreteField.MySomething.ToString());
    }
}

答案 1 :(得分:1)

我会重构这个以使用依赖注入。这样,该类不包含用于创建其依赖的其他类的代码,例如myConcreteField = new ConcreteA<T>(4);。依赖注入用于防止代码陷入这样的困难结。

(你的例子是非常非常抽象的,这使得它有点困难。如果你使用像&#34这样的类名;混凝土&#34;和#34;实施&#34;那么它使答案更难以阅读因为我们使用相同的词语来描述概念。)

相反,无论Concrete是什么,都要声明一个接口,比如

public interface ISomethingThatTheOtherClassNeeds<T>
{
    public int MySomething {get;set;}
}

public class SomethingThatTheOtherClassNeeds : ISomethingThatTheOtherClassNeeds<string>
{
    public int MySomething {get;set;}
}

然后在你的Implementation课程中:

class Implementation<T>
{
    private readonly ISomethingThatTheOtherClassNeeds<T> _something;

    public Implementation(ISomethingThatTheOtherClassNeeds<T> something)
    {
        _something = something;
    }

    void DoSomething()
    {
        Console.Write(_something.MySomething.ToString());
    }
}

不同之处在于,它不是负责创建该类的任何内容,而是在构造函数中传递给ImplementationImplementation甚至不知道该类是什么 - 它只知道它与界面匹配。

如果其他类依赖于更多类,这将特别有用。如果您通过在班级中调用new来创建它们,那么该类必须知道如何创建这些类。

然后将它连接起来,您将使用依赖注入容器,如Windsor,Unity,Autofac等等。这对于控制台应用程序来说并不常见,但我猜测这比实际更具实验性。