繁体   English   中英

让一个类将自己作为参数传递给泛型基类邪恶?

[英]Is letting a class pass itself as a parameter to a generic base class evil?

我第一次看到一位同事在实施对象池时这样做了。 他将要作为参数汇集的类传递给泛型基类。 这个基类列出了池代码。

奇怪的是基类会知道它的孩子。 在每种正常情况下,这被认为是不好的做法。 但在这种情况下,父母只是避免编写重复代码的技术解决方案。 任何其他代码都不会引用基类。

这种结构的一个缺点是它“烧掉了基础类”。 您不能在层次结构的中间引入通用基类。 此问题可能超出了主题范围。

以下是一个可以想象的例子:

public abstract class Singleton<T> where T : class
{
    public static T Instance { get; private set; }

    public Singleton()
    {
        if (Instance != null)
            throw new Exception("Singleton instance already created.");
        Instance = (T) (object) this;
    }
}

public class MyClass : Singleton<MyClass>
{
}

改进代码:

public abstract class Singleton<T> where T : Singleton<T>
{
    public static T Instance { get; private set; }

    public Singleton()
    {
        if (Instance != null)
            throw new Exception("Singleton instance already created.");
        Instance = (T) this;
    }
}

public class MyClass : Singleton<MyClass>
{
}

没有; 这是一种众所周知的模式,称为CRTP
它在C ++中作为虚拟方法的替代方法特别有用。

您可以在IComparable<T>IEquatable<T>的.Net框架内看到它。

为了增加稳健性,您应该添加where T : Singleton<T>

SLaks是正确的 - 这是一个有用的模式,通常适用于您希望在基类中提供强类型派生类的代码。

您还通常会向泛型参数添加类型约束,以指示泛型类型必须从抽象类型继承。 添加此约束的语法看起来是递归的,但不要对此感到恐慌 - 它不是递归计算的,只是确保唯一有效的泛型类型是派生类。

例如,假设您经营茶和咖啡混合业务。 你可以将咖啡加上咖啡,茶和茶混合,但你要确保你不能将咖啡与茶混合。 但是,由于它们都是饮料,因此您希望以相同的方式对它们进行建模。

public abstract class Beverage<T> where T : Beverage<T>
{
    public abstract T Blend(T drink1, T drink2);
}

public class Tea : Beverage<Tea>
{
    public override Tea Blend(Tea drink1, Tea drink2)
    { 
        // Blend tea here.
    }
}
public class Coffee : Beverage<Coffee>
{
    public override Coffee Blend(Coffee drink1, Coffee drink2)
    { 
        // Blend coffee here.  Although coffee is nasty, so
        // why you'd want to is beyond me.
    }
}

在阅读有关CRTP的内容时,值得记住的是,C ++模板只是表面上类似于C#泛型。 关键的区别在于模板实际上是一个在编译时工作的代码生成工具,而C#泛型在运行时是受支持的。

此外,编写这样的代码会降低可读性。 因此,尽管确实存在这种正确方法,但您应该考虑一下您要解决的问题,看看是否有更简单的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM