如何在 C# 中确保对象的类型等于此?
How to ensure in C# that the type of an object is equal to this?
问题
我有以下界面(可以更改,但仅供参考):
public interface IObj<T>
{
void Merge(IObj<T> other);
}
问题出在 Merge
操作上。我无法找到一种方法来确保传递给该方法的参数与 this
的类型相同。例如看看下面的实现:
public class A<T> : IObj<T>
{
public void Merge(IObj<T> other)
{
var casted = other as A<T>;
if (casted == null)
throw new ArgumentException("Incorrect type.");
// do the actual stuff
}
}
任何实现接口的对象总是需要与相同类型的实例合并。因此,我需要编写此样板代码以在执行任何操作之前尝试转换。
问题
是否可以通过合同/接口/其他方式来确保这一点?
您可以尝试使用 self-referencing generic pattern。
它经常用于可继承对象的流畅构建器。
对于你的情况,它应该是这样的:
public interface IObj<T, TSelf> where TSelf : IObj<T, TSelf>
{
void Merge(TSelf other);
}
class A<T>: IObj<T, A<T>> {
public void Merge(A<T> alreadyCasted) {
}
}
不幸的是,这也引入了样板代码(在 class A 的声明中)。但是当你在 base class.
的接口中有很多方法时,这很好
据我所知,没有其他变体。
根据@nsinreal 的解决方案,我建议你在接口上的另一个层次(和一个抽象class,以避免多次实现接口):
public interface IObj<T>
{
void Merge(IObj<T> other);
}
public interface IObj<T, TImplementor> : IObj<T>
where TImplementor : class, IObj<T, TImplementor>
{
void Merge(TImplementor other);
}
public abstract class AObj<T, TImplementor> : IObj<T, TImplementor>
where TImplementor : class, IObj<T, TImplementor>
{
public abstract void Merge(TImplementor other);
void IObj<T>.Merge(IObj<T> other)
{
var casted = other as TImplementor;
if (casted == null)
throw new ArgumentException("Incorrect type.");
Merge(casted);
}
}
public class A<T> : AObj<T, A<T>>
{
override public void Merge(A<T> other)
{
// do the actual stuff
}
}
public class B<T> : AObj<T, B<T>>
{
override public void Merge(B<T> other)
{
// do the actual stuff
}
}
现在,对于名为 SpecificObj<T>
的 class,您有两种方法:
void Merge(IObj<T>)
void Merge(SpecificObj<T>)
您仍然可以将其用作 IObj<T>
仍然不确定是否能完全解决您的问题。
问题
我有以下界面(可以更改,但仅供参考):
public interface IObj<T>
{
void Merge(IObj<T> other);
}
问题出在 Merge
操作上。我无法找到一种方法来确保传递给该方法的参数与 this
的类型相同。例如看看下面的实现:
public class A<T> : IObj<T>
{
public void Merge(IObj<T> other)
{
var casted = other as A<T>;
if (casted == null)
throw new ArgumentException("Incorrect type.");
// do the actual stuff
}
}
任何实现接口的对象总是需要与相同类型的实例合并。因此,我需要编写此样板代码以在执行任何操作之前尝试转换。
问题
是否可以通过合同/接口/其他方式来确保这一点?
您可以尝试使用 self-referencing generic pattern。 它经常用于可继承对象的流畅构建器。
对于你的情况,它应该是这样的:
public interface IObj<T, TSelf> where TSelf : IObj<T, TSelf>
{
void Merge(TSelf other);
}
class A<T>: IObj<T, A<T>> {
public void Merge(A<T> alreadyCasted) {
}
}
不幸的是,这也引入了样板代码(在 class A 的声明中)。但是当你在 base class.
的接口中有很多方法时,这很好据我所知,没有其他变体。
根据@nsinreal 的解决方案,我建议你在接口上的另一个层次(和一个抽象class,以避免多次实现接口):
public interface IObj<T>
{
void Merge(IObj<T> other);
}
public interface IObj<T, TImplementor> : IObj<T>
where TImplementor : class, IObj<T, TImplementor>
{
void Merge(TImplementor other);
}
public abstract class AObj<T, TImplementor> : IObj<T, TImplementor>
where TImplementor : class, IObj<T, TImplementor>
{
public abstract void Merge(TImplementor other);
void IObj<T>.Merge(IObj<T> other)
{
var casted = other as TImplementor;
if (casted == null)
throw new ArgumentException("Incorrect type.");
Merge(casted);
}
}
public class A<T> : AObj<T, A<T>>
{
override public void Merge(A<T> other)
{
// do the actual stuff
}
}
public class B<T> : AObj<T, B<T>>
{
override public void Merge(B<T> other)
{
// do the actual stuff
}
}
现在,对于名为 SpecificObj<T>
的 class,您有两种方法:
void Merge(IObj<T>)
void Merge(SpecificObj<T>)
您仍然可以将其用作 IObj<T>
仍然不确定是否能完全解决您的问题。