C# 使用可变类型的参数重写方法
给出以下示例:C# 使用可变类型的参数重写方法,c#,overriding,C#,Overriding,给出以下示例: class A { } class B : A { } class C : A { } 我希望所有继承的类都实现一个函数,该函数执行特定于这些类的单独实例的数据比较。我面临的问题是,其中一个参数的类型与实现此方法的类的类型相同。比如: class A { public virtual void CompareSomeData(A instanceOfA) { } } class B : A { public override void CompareSom
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?
}
或
还是其他方法
这里的想法是,我想从带有类型约束的泛型方法调用这些方法:
private void CompareData<T>(List<T> dataOld, List<T> dataNew) where T : A
{
foreach (T item in dataNew)
{
item.CompareSomeData(GetItemToCompare(dataOld));
}
}
private void CompareData(List dataOld,List dataNew),其中T:A
{
foreach(dataNew中的T项)
{
item.CompareMedata(GetItemToCompare(dataOld));
}
}
编辑:
我的建议和Marc的答案仍然存在一个问题,那就是这些都不是类型安全的。如果没有在方法中进行检查(
if(instanceOfA是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) {
// ...
}
}
重写时不能更改签名,但可以在并行重写时重载该方法,例如:
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);
}
}
接口IDataComparer
{
void CompareSomeData(T实例);
}
A级:IDataComparer
{
公共虚拟空比较元数据(实例fa){}
}
B类:A,IDataComparer
{
公共覆盖无效比较元数据(实例FA)
{
抛出新的ArgumentException(“…”);
}
公共虚拟空比较元数据(B实例FB)
{
base.CompareSomeData(instanceOfB);
}
}
C类:A,IDataComparer
{
公共覆盖无效比较元数据(实例FA)
{
抛出新的ArgumentException(“…”);
}
公共虚拟空比较元数据(C instanceOfC)
{
base.CompareSomeData(instanceOfC);
}
}
然后在您的
CompareData
方法中,您将使用约束T:IDataComparer
这很难看,但是在不强制转换或要求类知道从它们继承的类的情况下确保类型安全的一种方法是:
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);
}
}
接口IDataComparer
{
void CompareSomeData(T实例);
}
A级:IDataComparer
{
公共虚拟空比较元数据(实例fa){}
}
B类:A,IDataComparer
{
公共覆盖无效比较元数据(实例FA)
{
抛出新的ArgumentException(“…”);
}
公共虚拟空比较元数据(B实例FB)
{
base.CompareSomeData(instanceOfB);
}
}
C类:A,IDataComparer
{
公共覆盖无效比较元数据(实例FA)
{
抛出新的ArgumentException(“…”);
}
公共虚拟空比较元数据(C instanceOfC)
{
base.CompareSomeData(instanceOfC);
}
}
然后在CompareData
方法中,您将使用约束T:IDataComparer
快速免责声明(Rant):
我不太喜欢方法重载(相同的标识符、不同的参数类型或不同的参数数量)。而且,如果它与方法重写(虚拟方法)混合使用,那么事情会变得更复杂
提出的解决方案:
反其道而行之。与其重载或重写处理参数的类,不如重载或重写作为参数的类
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
我不记得这种技术的名字,“访问者模式”,“调度”,随便什么
希望能有帮助
另外,别忘了给小猫一个打开的金枪鱼罐头快速免责声明(Rant):
我不太喜欢方法重载(相同的标识符、不同的参数类型或不同的参数数量)。而且,如果它与方法重写(虚拟方法)混合使用,那么事情会变得更复杂
提出的解决方案:
反其道而行之。与其重载或重写处理参数的类,不如重载或重写作为参数的类
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
我不记得这种技术的名字,“访问者模式”,“调度”,随便什么
希望能有帮助
另外,别忘了给小猫一个开着的金枪鱼罐头,所以在我的例子中,答案是超负荷和超负荷。第二部分是方法隐藏,但我的方法无论如何都是无效的(通过传递一个对象来积累所有差异的集合)。因此,在我的例子中,答案是重写和重载。第二部分是方法隐藏,但我的方法无论如何都是无效的(传递一个对象以积累所有差异的集合)。关于编辑中的问题,你是说你担心,例如,调用
CompareData
时,C
的一个实例可能被强制转换为aB
,然后放入dataOld
或dataNew
列表?嗯,不完全是因为B和C不会相互强制转换