覆盖抽象类'函数与另一个带有“类类型”的函数不同.返回类型
本文关键字:函数 类类型 类型 返回类型 抽象类 另一个 覆盖 | 更新日期: 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;
}
}
例子:
<标题> 1DayInfo 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
接口。