首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >让类将自身作为参数传递给泛型基类是不好的吗?

让类将自身作为参数传递给泛型基类是不好的吗?
EN

Stack Overflow用户
提问于 2013-10-08 19:49:22
回答 2查看 2.7K关注 0票数 16

我第一次看到一个同事这样做是在他实现对象池的时候。他将将要池化的类作为参数传递给一个泛型基类。这个基类布置了池化代码。

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

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

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

代码语言:javascript
复制
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>
{
}

改进的代码:

代码语言:javascript
复制
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>
{
}
EN

回答 2

Stack Overflow用户

发布于 2013-10-08 19:51:26

不是;这是一种众所周知的模式,称为CRTP

作为虚拟方法的替代,它在C++中特别有用。

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

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

票数 14
EN

Stack Overflow用户

发布于 2013-10-08 20:31:39

SLaks是正确的--这是一个有用的模式,通常适用于当你想在你的基类中提供强类型到你的派生类的代码时。

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

例如,假设您经营一家茶和咖啡混合业务。对你来说,混合咖啡和咖啡、茶和茶是有意义的,但你要确保不能把咖啡和茶混合在一起。但是,因为它们都是饮料,所以您希望以相同的方式对它们进行建模。

代码语言:javascript
复制
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.
    }
}

在阅读有关C#的文章时,值得记住的是C++模板只是表面上类似于CRTP泛型。关键的区别在于模板是有效的代码生成工具,它在编译时工作,而C#泛型在运行时得到支持。

此外,像这样编写代码会降低可读性。因此,尽管在某些情况下这是正确的方法,但您应该考虑一下您正在尝试解决的问题,看看是否有更直接的方法。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19246937

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档