覆盖抽象类'函数与另一个带有“类类型”的函数不同.返回类型

本文关键字:函数 类类型 类型 返回类型 抽象类 另一个 覆盖 | 更新日期: 2023-09-27 18:13:00

我正在尝试创建一个基于抽象类的类,并将基类中包含的函数覆盖为另一个具有返回类型"T"的函数,该函数是由类传递的类型。

例句:

public abstract class DayInfo
{
    public virtual void GetInfo()
    {
        throw new NotImplementedException();
    }
}
public class DayInfo<T> : DayInfo
{
    private T info;
    public DayInfo(T data)
    {
        info = data;
    }
    public T GetInfo() // << This
    {
        return info;
    }
}

例子:

<标题> 1
DayInfo info = new DayInfo<String>("Blah");
String stuff = info.GetInfo();
<标题> 2 h1> 否有任何方法来实现这一点?

编辑1:我忘了说明我没有在基类中使用类传递的类型,因为我希望能够将其作为泛型类型使用,而不必定义任何类型。

e。g:

public SortedDictionary<int, DayInfo> Data = new SortedDictionary<int, DayInfo>();
编辑2:

此外,基类中的虚函数的意义在于,如果访问了GetInfo()函数但未被覆盖,它将使子类抛出异常。

覆盖抽象类'函数与另一个带有“类类型”的函数不同.返回类型

这是实现你的目标的方法:

public abstract class DayInfoA<T>
{
    public virtual T GetInfo()
    {
        .......
    }
}
public class DayInfoB<T> : DayInfoA<T>
{
    private T info;
    public DayInfoB(T data)
    {
        info = data;
    }
    public override T GetInfo() // << This
    {
      .........
    }
}

,并像这样使用:

        DayInfoB<int> info = new DayInfoB<int>(25);
        int stuff = info.GetInfo();

为什么不将GetInfo()声明为dynamic ?这样铸造应该是自动的。唯一的缺点是你失去了编译器断言,如果存储GetInfo()值的变量不能进行强制转换,它会抛出一个运行时错误。

例如:

public abstract class DayInfo {
    public abstract dynamic GetInfo();
}
public class DayInfo<T> : DayInfo {
    private readonly T _info;
    public DayInfo(T info) {
        _info = info;
    }
    public override dynamic GetInfo() {
        return _info;
    }
}

你也可以声明像GetInfo<T>(ref T result)这样的东西,这样你可以从方法调用中省略T类型,让编译器在运行时推断它,唯一的缺点是你应该传递变量来存储结果作为一个参数,而不是让它由方法返回。

这可以用NVI模式生成:

public abstract class DayInfo
{
  protected virtual void GetInfoCore() {
    throw new NotImplementedException();
  }
  // or
  // protected abstract void GetInfoCore();
  public void GetInfo() {
    GetInfoCore();
  }
}
public class DayInfo<T> : DayInfo
{
  private T info;
  public DayInfo(T data) {
    info = data;
  }
  public new T GetInfo() { // << This
    return info;
  }
  protected override void GetInfoCore() {
    GetInfo();
  }
}

不,看起来不像您想要的那样(假设您不想或不能更改基类声明)。为了使函数解析为多态调用,您需要具有相同的签名和返回类型。否则它不会以多态方式解析函数,它只会调用函数的基类版本,因为这就是它看到你调用的(并且你已经分配实例的变量是基类类型)。

你可以这样做,但是很难看:

        DayInfo info = new DayInfo<String>("Blah");
        String stuff = ((DayInfo<string>)info).GetInfo();

不能,因为函数不会匹配不同的函数签名。

你可以这样定义它:

public abstract class DayInfo
{
    public virtual object GetInfo()
    {
        throw new NotImplementedException();
    }
}

和在派生类中:

public object GetInfo() // << This
{
    return info;
}

那么它们将具有相同的签名,并且多态性将匹配。然而,在另一端则需要强制转换:

DayInfo info = new DayInfo<int>(25);
int stuff = (int)info.GetInfo();

编辑:作为题外话,除非有更多的东西,否则我会把它变成一个界面,或者如果GetInfo真的什么都不做,那么GetInfo就纯粹是抽象的。

public abstract object GetInfo();

您可以创建协变接口,而不是基类,或者除了基类之外:

void Main()
{
    IDayInfo dayInfo = new DayInfo<string>("hi!");
    object info = dayInfo.GetInfo(); //info == "hi!"
}
public interface IDayInfo
{
    object GetInfo();
}
public interface IDayInfo<out T> : IDayInfo
{
    new T GetInfo();
}
public class DayInfo<T> : IDayInfo<T>
{
    private T info;
    public DayInfo(T data)
    {
        info = data;
    }
    public T GetInfo()
    {
        return info;
    }
    object IDayInfo.GetInfo()
    {
        return this.GetInfo();
    }
}

(参见通用接口中的方差,了解什么是协方差/逆变方差)

请注意,object info(在Main的第二行中)是在本例中无需强制转换即可获得的最精确的值。一旦将DayInfo<string>对象存储在IDayInfo<object>变量/字段中,就像我所做的那样(正如您希望在字典中所做的那样),从某种意义上说,string的强类型被遗忘了,如果不进行强制类型转换就无法恢复。

更新:添加IDayInfo接口。