用可变类型的参数重写方法
本文关键字:参数 重写 方法 类型 | 更新日期: 2023-09-27 18:05:40
给定以下示例:
class A { }
class B : A { }
class C : A { }
我希望所有继承类都实现一个函数,该函数执行特定于这些类的单独实例的数据比较。我面临的问题是,其中一个参数的类型与实现此方法的类的类型相同。比如:
class A
{
public virtual void CompareSomeData(A instanceOfA) { }
}
class B : A
{
public override void CompareSomeData(B instanceOfB)
{
base.CompareSomeData(instanceOfB);
}
}
class C : A
{
public override void CompareSomeData(C instanceOfC)
{
base.CompareSomeData(instanceOfC);
}
}
显然你不能以这种方式在c#中重写方法。那么什么是最好的模式呢?
public virtual void CompareSomeData(object instance, Type typeOfInstance)
{
// Cast the object to an instance of the type here?
}
或
public virtual void CompareSomeData(A instanceOfA, Type typeOfInstance)
{
// Cast the object to an instance of the type here?
}
或其他方法?
这里的想法是,我想从具有类型约束的泛型方法调用这些方法:private void CompareData<T>(List<T> dataOld, List<T> dataNew) where T : A
{
foreach (T item in dataNew)
{
item.CompareSomeData(GetItemToCompare(dataOld));
}
}
编辑:
在我的建议和Marc的回答中,我仍然看到的问题是这些确实不是类型安全的。如果没有在方法(if (instanceOfA is B) { ... }
)中进行检查,我无法保证传递给B的对象确实是B。我不知道是否有任何方法可以解决这个问题,但我可能只需要使用它并抛出ArgumentException
或其他东西
不能在重写时更改签名,但可以在并行重写时重载方法,例如:
class A {
public virtual void CompareSomeData(A instanceOfA) { }
}
class B : A {
public void CompareSomeData(B instanceOfB) {
// ...
}
public override void CompareSomeData(A instanceOfA) {
// ...
}
}
请注意,这两个方法中的一个调用另一个方法(逻辑只在一个地方)是很常见的,但是哪个方法应该调用哪个方法是特定于实现的。
还请注意,如果您只更改返回类型,则需要采用不同的方式:class A {
public bool CompareSomeData(A instanceOfA) {
return CompareSomeDataImpl(instanceOfA);
}
protected virtual bool CompareSomeDataImpl(A instanceOfA)
{ return true; }
}
class B : A {
public new string CompareSomeData(A instanceOfA) {
// ...
}
protected override bool CompareSomeDataImpl(A instanceOfA) {
// ...
}
}
这很难看,但有一种方法可以确保类型安全,而不需要强制转换或要求类知道从它们继承的类:
interface IDataComparer<T>
{
void CompareSomeData(T instance);
}
class A : IDataComparer<A>
{
public virtual void CompareSomeData(A instanceOfA) { }
}
class B : A, IDataComparer<B>
{
public override void CompareSomeData(A instanceofA)
{
throw new ArgumentException("...");
}
public virtual void CompareSomeData(B instanceOfB)
{
base.CompareSomeData(instanceOfB);
}
}
class C : A, IDataComparer<C>
{
public override void CompareSomeData(A instanceofA)
{
throw new ArgumentException("...");
}
public virtual void CompareSomeData(C instanceOfC)
{
base.CompareSomeData(instanceOfC);
}
}
然后在CompareData<T>
方法中,您将使用约束T : IDataComparer<T>
快速免责声明(咆哮):
我不太喜欢方法重载(相同的标识符,不同的参数类型或不同的参数数量)。而且,如果它混合了方法重写(虚拟方法),事情会变得更复杂。
Propposed解决方案:
逆过程。不是重载或重写处理形参的类,而是重载或重写作为形参的类。
public abstract class ParameterDataClass
{
public abstract bool CompareTo(StreamClass Stream);
} // class ParameterDataClass
public /* concrete */ class DataComparerClass
{
internal /* nonvirtual */ void InternalComparison(string Data) { ... }
public /* nonvirtual */ bool CompareThis(ParameterDataClass Data)
{
bool Result = false;
if (Data != null)
{
Result = Data.CompareTo(this);
}
} // bool CompareThis(...)
} // class StreamClass
public /* concrete */ class CustomerClass: StreamDataClass
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
public override bool CompareTo(StreamClass Stream)
{
bool Result = false;
if (Stream!= null)
{
string Temp = "{" +
FirstName.ToString() + "," +
LastName.ToString() + "," +
BirthDate.ToString() + "}"
Result = Data.CompareTo(Temp);
}
} // bool CompareTo(...)
return Result;
} // class CustomerClass
public /* concrete */ class AreaClass: StreamDataClass
{
public int Top { get; set; }
public int Left { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public override bool CompareTo(StreamClass Stream)
{
bool Result = false;
if (Stream!= null)
{
string Temp = "{" +
Top.ToString() + "," +
Left.ToString() + "," +
Width.ToString() + "," +
Height.ToString() + "}"
Result = Data.CompareTo(Temp);
}
} // bool CompareTo(...)
return Result;
} // class AreaClass
public /* concrete */ class IntegerClass: StreamDataClass
{
public int RealVaLue { get; set; }
public override bool CompareTo(StreamClass Stream)
{
bool Result = false;
if (Stream!= null)
{
Result = Data.CompareTo(RealValue.ToString());
}
} // bool CompareTo(...)
return Result;
} // class IntegerClass
我不记得这个技术的名字了,"访问者模式","调度",等等。
希望有帮助。
注:别忘了给小猫一个打开的金枪鱼罐头