抽象泛型类采用本身派生自该类的类型参数
您认为创建一个将派生自自身的类作为类型参数的抽象泛型类是可接受的还是不好的做法?
这允许抽象泛型类操作派生类的实例,特别是根据需要创建派生类的 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;
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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这有点主观,但我不太喜欢隐式转换。当您使用它们时,代码常常会产生误导,有时如果是由隐式强制转换引起的错误,则很难找到错误。如果您的课程只是为了使用它们而设计的,那么我不会以这种方式使用它。
因为您定义了来自
CoolClass
的转换,而不是来自CoolInt
的转换。它们是不同的类型。如果您在 CoolInt 实现中使用此方法,它将起作用:关于泛型的使用:
如果您需要使用许多类创建复杂的继承层次结构(例如引入新的类),则泛型的这种使用会对您的体系结构产生限制。抽象级别可能很棘手)。但这实际上取决于您的需要。我实际上在一个项目中使用了这种技术来避免代码重复。如果您的
CoolClass
克服 new() 限制,您也可以将委托Func
传递给构造函数:)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.
Because you defined convertion from
CoolClass<T, U>
, but not from theCoolInt
. They are different types. It would work if you had this method in your CoolInt implementation: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 yourCoolClass
to overcome new() restriction :)这是 C++ 中的一种常见(而且很好!)模式,看起来有点像这样:
我们将它与其他模式一起用于静态多态性/继承。
然而,在 .NET 中,通用参数在运行时并且还存在反射,我不完全确定好处在哪里。我的意思是,拥有派生类型很有用,但您必须问自己 - 有什么用,以及它与直接继承有何不同?
It's a common (and good!) pattern in C++, that looks a little like this:
We use it for static polymorphism/inheritance, along with others.
However, in .NET where generic parameters are at runtime and there is also reflection, I'm not entirely sure where the benefit would be. I mean, having the derived type is useful, but you have to ask yourself- useful for what, and how does it differ from straight inheritance?