首页 文章

抽象泛型类采用本身派生自该类的类型参数

提问于
浏览
5

您是否认为创建一个抽象泛型类是一种可接受或不好的做法,该类将类型参数作为一个派生自己的类?

这允许抽象泛型类操作派生类的实例,特别是在必要时创建派生类的new()实例的能力,并且可以帮助避免从派生类派生的具体类中重复代码 .

如果“糟糕”你更喜欢处理这种情况的替代方案,你将如何构建下面的代码?

例如:-

// We pass both the wrapped class and the wrapping class as type parameters 
    // to the generic class allowing it to create instances of either as necessary.

    public abstract class CoolClass<T, U>
        where U : CoolClass<T, U>, new()
    {
        public T Value { get; private set; }
        protected CoolClass() { }
        public CoolClass(T value) { Value = value; }
        public static implicit operator CoolClass<T, U>(T val)
        {
            // since we know the derived type and that its new(), we can
            // new up an instance of it (which we couldn't do as an abstract class)
            return new U() { Value = val};
        }
        public static implicit operator T(CoolClass<T, U> obj)
        {
            return obj.Value;
        }
    }

还有第二个问题:为什么这些隐式算子中的一个有效,而另一个没有?

例如

public class CoolInt : CoolClass<int, CoolInt>
    {
        public CoolInt() {  }
        public CoolInt(int val) (val) { }
    }

                                    // Why does this not work
        CoolInt x = 5;
                                    // when this works
        CoolInt x2 = (CoolInt)5;    
                                    // and this works
        int j = x;

2 回答

  • 1

    这有点主观,但我不是隐性演员的忠实粉丝 . 当你使用代码时,代码经常会产生误导,有时如果是由implisit强制转换引起的,很难找到错误 . 如果你的课程只是为了使用而设计,那么我就不会这样使用它 .

    为什么这些隐式运算符中的一个工作而另一个不工作?

    因为您定义了 CoolClass<T, U> 的转换,而不是 CoolInt . 它们是不同的类型 . 如果你在CoolInt实现中有这个方法,它会工作:

    public static implicit operator CoolInt(int val)
    

    关于泛型的用法:

    如果您需要使用许多类创建复杂的继承层次结构(例如,引入新的抽象级别可能会非常棘手),那么泛型的这种使用会给您的体系结构带来限制 . 但这真的取决于你需要什么 . 我实际上在其中一个项目中使用了这样的tecnique来避免代码重复 . 如果您的 CoolClass 克服new()限制,您也可以将委托 Func<U> 传递给构造函数:)

  • 1

    这是C中常见的(也是好的!)模式,看起来有点像这样:

    template<typename T> class Base {
        void foo() { T::foo(); /* Call the derived implementation*/ }
    };
    class Derived : public Base<Derived> {
        void foo() { /* do something*/ }
    };
    

    我们将它用于静态多态/继承以及其他 .

    但是,在.NET中,泛型参数在运行时并且还有反射,我不完全确定它的好处 . 我的意思是,使用派生类型是有用的,但你必须问自己 - 对于什么有用,它与直接继承有什么不同?

相关问题