用可变类型的参数重写方法

本文关键字:参数 重写 方法 类型 | 更新日期: 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

我不记得这个技术的名字了,"访问者模式","调度",等等。

希望有帮助。

注:别忘了给小猫一个打开的金枪鱼罐头