Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics 抽象泛型类,其类型参数本身派生自该类 你认为创建一个抽象泛型类是一个可接受还是不好的做法,它是一个类型参数,它是一个派生自它的类?p>_Generics_Abstract Class - Fatal编程技术网

Generics 抽象泛型类,其类型参数本身派生自该类 你认为创建一个抽象泛型类是一个可接受还是不好的做法,它是一个类型参数,它是一个派生自它的类?p>

Generics 抽象泛型类,其类型参数本身派生自该类 你认为创建一个抽象泛型类是一个可接受还是不好的做法,它是一个类型参数,它是一个派生自它的类?p>,generics,abstract-class,Generics,Abstract Class,这允许抽象泛型类操作派生类的实例,特别是在必要时创建派生类的新()实例的能力,并有助于避免在派生的具体类中重复代码 如果“坏”的话,你更喜欢用什么方法来处理这种情况?你会如何构造下面的代码 例如:- // We pass both the wrapped class and the wrapping class as type parameters // to the generic class allowing it to create instances of either

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

如果“坏”的话,你更喜欢用什么方法来处理这种情况?你会如何构造下面的代码

例如:-

    // 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;
        }
    }
//我们将包装类和包装类作为类型参数传递
//到泛型类,允许它根据需要创建其中一个的实例。
公共抽象类
其中U:CoolClass,new()
{
公共T值{get;私有集;}
受保护的CoolClass(){}
公共CoolClass(T值){value=value;}
公共静态隐式运算符CoolClass(T val)
{
//因为我们知道派生类型及其new(),所以我们可以
//新建它的一个实例(我们不能将其作为抽象类)
返回新的U(){Value=val};
}
公共静态隐式运算符T(CoolClass obj)
{
返回对象值;
}
}
还有第二个额外的问题:为什么这些隐式操作符中的一个有效而另一个无效

e、 g

公共类CoolInt:CoolClass
{
公共CoolInt(){}
公共CoolInt(int-val)(val){}
}
//为什么这不起作用
CoolInt x=5;
//当这起作用时
CoolInt x2=(CoolInt)5;
//这是有效的
int j=x;

这有点主观,但我不太喜欢隐式类型转换。当您使用它们时,代码常常会产生误导,如果它是由implisit强制转换引起的,则有时很难找到错误。如果你的类是专为使用它们而设计的,那么我就不会这样使用它

为什么这些隐式运算符中的一个有效,而另一个无效

因为您是从
CoolClass
定义转换的,而不是从
CoolInt
定义转换的。它们是不同的类型。如果在CoolInt实现中使用此方法,它将起作用:

public static implicit operator CoolInt(int val)
关于泛型的用法:

如果您需要创建包含许多类的复杂继承层次结构(例如,引入新的抽象级别可能很棘手),那么泛型的使用会对您的体系结构造成限制。但这取决于你需要什么。实际上,我在其中一个项目中使用了这种技术,以避免代码重复。如果你的代码> CoolClass < /COD>克服了新的()限制:(

< p>这是C++中常见的(而且是好的)模式,看起来有点像:

template<typename T> class Base {
    void foo() { T::foo(); /* Call the derived implementation*/ }
};
class Derived : public Base<Derived> {
    void foo() { /* do something*/ }
};
模板类基类{
void foo(){T::foo();/*调用派生实现*/}
};
派生类:公共基{
void foo(){/*做点什么*/}
};
我们将它与其他工具一起用于静态多态性/继承


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

关于泛型类型参数的问题呢?(我应该把这个隐含的问题放在一个单独的问题中,因为这有点分散了我对主要问题的注意力。)+1但我不同意不赞成隐含的演员阵容。没有任何代码是在没有静态分析或认真使用调试器的情况下无法发现的;作为一名开发人员,我希望必须这样做才能分析更复杂的代码。复杂并不等于坏。在这种情况下,它使类的使用者更能够做他们想做的事情。+1-但我真正希望在C#中能够做的是奇怪的递归模板-C#没有太多的预编译程序可谈,这真是遗憾!有趣的是,您提到了事物的反射方面——我开发了一个组件,动态编译派生类或接口的实现,以内置横切之类的东西。虽然我很欣赏在.Net中可以相对轻松地完成这类事情,但这意味着这是一条陡峭的学习曲线。
template<typename T> class Base {
    void foo() { T::foo(); /* Call the derived implementation*/ }
};
class Derived : public Base<Derived> {
    void foo() { /* do something*/ }
};