【问题标题】:Workaround the lack of 'new(parameters)' in generic in C#解决 C# 中泛型中缺少“新(参数)”的问题
【发布时间】:2014-12-24 18:44:42
【问题描述】:

我找到了两种方法来解决泛型中缺少“新(参数)”的问题,但我想知道是否有更好的解决方案来解决这种情况。

我需要在 Earth 中使用 Dna 作为 ctor 中的参数创建任何水果的方法。我有很多水果。

使用 Activator(或任何类似形式)的缺点是,如果派生类没有修正器或抽象类,则会中断。

public class Earth
{
    public Earth()
    {
        var dna = new Dna();
        var orange = GetFruit<Orange>(dna);
    }

    private static T GetFruit<T>(Dna dna) where T : Fruit
    {
        return (T)Activator.CreateInstance(typeof(T), dna);
    }
}

public abstract class Fruit
{
    public Fruit(Dna dna)
    {

    }
}

public class Orange : Fruit
{
    public Orange(Dna dna)
        : base(dna)
    {

    }
}

public class Dna
{

}

使用无参数 ctor 的缺点是强制 Dna 变为可选。 'Initialize(Dna dna)' 方法也是如此。

public class Earth
{
    public Earth()
    {
        var dna = new Dna();
        var orange = GetFruit<Orange>(dna);
    }

    private static T GetFruit<T>(Dna dna) where T : Fruit, new()
    {
        return new T() { Dna = dna };
    }
}

public abstract class Fruit
{
    public Dna Dna { get; set; }
}

public class Orange : Fruit
{

}

public class Dna
{

}

【问题讨论】:

    标签: c# generics


    【解决方案1】:

    一种选择是添加另一个参数:Func&lt;Dna, T&gt;:

    private static T GetFruit<T>(Dna dna, Func<Dna, T> ctor) where T : Fruit
    {
        // I assume your real code does more here?
        return ctor(dna);
    }
    

    那么你可以使用:

    var orange = GetFruit(dna, x => new Orange(x));
    

    请注意,这也意味着您不需要明确指定类型参数。不利的一面是,如果您要从 另一个 泛型方法调用它,则需要在整个堆栈中传递构造委托:(

    【讨论】:

    • 真正的代码更复杂,正如您所指出的,您的解决方案运行良好,因为它避免了 Activator 的代码气味。
    猜你喜欢
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-20
    • 1970-01-01
    • 2010-11-29
    • 2015-06-18
    相关资源
    最近更新 更多