抽象泛型类采用自己派生自该类的类型参数 [英] Abstract generic classes taking type parameters that are themselves derived from that class

查看:103
本文介绍了抽象泛型类采用自己派生自该类的类型参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你认为创建一个抽象泛型类是可接受的还是不好的做法,该泛型类将类型参数作为自身派生的类来使用?这允许抽象泛型类操纵派生类的实例,特别是能够根据需要创建派生类的new()实例,并且可以帮助避免从它派生的具体类中重复代码。



如果'不好',您更喜欢处理这种情况的替代方案,以及如何构造下面的代码?



例如: -

  // We将包装类和包装类作为类型参数
//传递给泛型类,以便根据需要创建实例。

公共抽象类CoolClass< T,U>
其中U:CoolClass< T,U>,new()
{
public T Value {get;私人设置; }
protected CoolClass(){}
public CoolClass(T value){Value = value; }
public static implicit operator CoolClass< T,U>(T val)
{
//由于我们知道派生类型和它的new(),我们可以
/ /新建它的一个实例(我们不能作为一个抽象类)
return new U(){Value = val};
}
public static implicit operator T(CoolClass< T,U> obj)
{
return obj.Value;


$ / code>

第二个奖金问题:为什么其中一个隐式运算符工作,另一个不工作?



eg

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

//为什么这不起作用
CoolInt x = 5;
//当这个工程
CoolInt x2 =(CoolInt)5;
//这可以工作
int j = x;


解决方案

这有点主观,但我不是隐含演员的大粉丝。当你使用代码时,代码通常会变得具有误导性,并且如果它是由于implisit强制转换造成的,有时很难找到一个错误。如果你的课程只是为了使用它们而设计的,那么我不会以这种方式使用它。


为什么其中一个隐式操作符有效,另一个不可操作?

由于您定义了来自 CoolClass< T,U> 的转换,但不是来自 CoolInt 。他们是不同的类型。如果你在你的CoolInt实现中使用了这个方法,它就会工作:

  public static implicit operator CoolInt(int val)

关于泛型的使用

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

Do you consider it an acceptable or a bad practice to create an abstract generic class that takes as a type parameter a class that derives from itself?

This allows the abstract generic class to manipulate instances of the derived class and in particular the ability to create new() instances of the derived class as necessary and can help avoid repeat code in the concrete classes that derive from it.

If 'bad' what alternative do you prefer to handle such situations and how would you structure the code below?

For example:-

    // 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;
        }
    }

And a second bonus question: why does ONE of these implicit operators work and the other one not?

e.g.

    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;

解决方案

It is a bit subjective but I'm not a big fan of the implicit casts. Code often becomes misleading when you use them and sometimes it is hard to find a bug if it is cause by implisit casts. If your class is designed only for use of them than I wouldn't use it in this way.

why does ONE of these implicit operators work and the other one not?

Because you defined convertion from CoolClass<T, U>, but not from the CoolInt. They are different types. It would work if you had this method in your CoolInt implementation:

public static implicit operator CoolInt(int val)

About usage of generics:

Such usage of generics creates limitations to your architecture if you would need to create complex inheritance hierarchies with many classes (e.g. introducing new level of abstraction could be tricky). But this really depends on what you need. I actually used such tecnique in one of the projects to avoid code duplication. Also you could pass a delegate Func<U> to the constructor if your CoolClass to overcome new() restriction :)

这篇关于抽象泛型类采用自己派生自该类的类型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆