我正在尝试创建一个基于抽象类的类,并使用另一个返回类型为“T”的类覆盖基类中包含的函数,该类是由类传递的类型。
e.g:
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;
}
}
示例:
DayInfo info = new DayInfo<String>("Blah");
String stuff = info.GetInfo();
DayInfo info = new DayInfo<int>(25);
int stuff = info.GetInfo();
有以任何方式来实现这一目标吗?
编辑1: 我忘了确切地说我没有在基类中使用类传递类型,因为我希望能够将它用作泛型类型,而不必定义任何类型。
例如:
public SortedDictionary<int, DayInfo> Data = new SortedDictionary<int, DayInfo>();
编辑2:
此外,基类中虚函数的要点是,如果访问GetInfo()函数但未被覆盖,它将使子类抛出异常。
答案 0 :(得分:1)
这是实现目标的方法:
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();
答案 1 :(得分:1)
为什么不将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
类型,让编译器在运行时推断它,唯一的缺点就是你应该传递变量将结果存储为参数,而不是通过方法返回它。
答案 2 :(得分:0)
不,不像它看起来像你想要它(假设你不想或不能改变基类声明)。为了使函数解析为多态调用,您需要具有相同的签名和返回类型。否则它不会以多态方式解析函数,它只会调用函数的基类版本,因为它看到你调用它(并且你为实例分配的变量属于基类类型)。
你可以做到这一点,但这很难看:
DayInfo info = new DayInfo<String>("Blah");
String stuff = ((DayInfo<string>)info).GetInfo();
答案 3 :(得分:0)
不,因为这些功能与不同的功能签名不匹配。
你能做的就是这样定义:
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();
答案 4 :(得分:0)
这可以使用NVI pattern生成:
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();
}
}
答案 5 :(得分:0)
您可以创建一个协变接口,而不是基类:
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();
}
}
(有关协方差/逆变的信息,请参阅Variance in Generic Interfaces)
请注意object info
(在Main
中的第二行)与此示例中未经强制转换的情况一样精确。将DayInfo<string>
对象存储在IDayInfo<object>
变量/字段中后,就像我一样(并且您希望在字典中执行此操作),string
的更强类型是一种感觉,被遗忘,没有演员就无法恢复。
更新:添加了IDayInfo
界面。