假设我有一个抽象类,如:
abstract class MyAbstractClass
{
public object GetValue(object parameter)
{
Console.WriteLine("Hello from object");
return parameter;
}
}
另外,我还有另一个扩展MyAbstractClass
的抽象类:
abstract class MyAbstractClass<T> : MyAbstractClass
{
public T GetValue(T parameter)
{
Console.WriteLine("Hello from generics");
return parameter;
}
}
使用string
作为泛型类型参数的简单具体类:
class MyImpClass : MyAbstractClass<string> { }
现在,我正在声明MyAbstractClass
列表(没有通用类型),添加MyImpClass
的实例并调用您的GetValue
方法。
public static void Main(string[] args)
{
IList<MyAbstractClass> list = new List<MyAbstractClass>();
list.Add(new MyImpClass());
list[0].GetValue("Testing...");
}
目前调用来自MyAbstractClass
的方法(没有通用类型参数)并打印出"Hello from object"
。
如果我直接从MyImpClass
的实例调用该方法,则会调用来自MyAbstractClass<T>
的方法。
new MyImpClass().GetValue("Testing...");
我这样做是因为在我的应用程序的某些部分,无论泛型类型参数如何,我都需要接收MyAbstractClass<T>
的实例。所以我使用MyAbstractClass
这样做。
我的问题是:有没有办法从MyAbstractClass<T>
调用MyAbstractClass
列表来调用方法?
我希望我已经足够清楚了。感谢。
答案 0 :(得分:4)
要直接调用泛型调用,您需要将其强制转换:
(list[0] as MyAbstractClass<string>)?.GetValue("Testing...");
但在我看来,这不是一个好的解决方案,你应该采取以下措施:
在您的通用类中覆盖非通用基类的GetValue
并在其中调用通用GetValue
:
abstract class MyAbstractClass<T> : MyAbstractClass
{
public T GetValue(T parameter)
{
Console.WriteLine("Hello from generics");
return parameter;
}
public override object GetValue(object parameter)
{
return GetValue((T)parameter);
}
}
或者,since C# 6.0,您也可以这样写:
public override object GetValue(object parameter) => GetValue((T)parameter);
您还需要将MyAbstractClass
的方法更改为虚拟:
public virtual object GetValue(object parameter)
答案 1 :(得分:3)
制作public object GetValue(object parameter)
virtual
,并在通用版本中覆盖它。
像这样:
abstract class MyAbstractClass
{
public virtual object GetValue(object parameter)
{
Console.WriteLine("Hello from object");
return parameter;
}
}
abstract class MyAbstractClass<T> : MyAbstractClass
{
override public object GetValue(object parameter)
{
return GetValue((T)parameter);
}
public T GetValue(T parameter)
{
Console.WriteLine("Hello from generics");
return parameter;
}
}
class MyImpClass : MyAbstractClass<string> { }
此代码:
void Main()
{
IList<MyAbstractClass> list = new List<MyAbstractClass>();
list.Add(new MyImpClass());
list[0].GetValue("Testing...");
}
现在生成以下输出:
来自仿制药的你好
我不确定有些人认为这没有回答这个问题。
如果从所有类中删除abstract
修饰符,请使用以下代码:
IList<MyAbstractClass> list = new List<MyAbstractClass>();
list.Add(new MyAbstractClass());
list.Add(new MyImpClass());
foreach (var item in list)
{
item.GetValue("Testing...");
}
它产生这个输出:
来自对象的你好 您好,来自仿制药
这似乎是OP最终希望代码执行的操作;迭代基类型的集合,如果实例是通用的,则调用泛型方法。
具体地将问题解释为要求方法的泛型版本是直接调用的方法,似乎忽略了我的X / Y问题。
答案 2 :(得分:2)
以这种方式无法实现您想要实现的目标。这将要求您覆盖方法,但您要做的是添加第二个方法,称为重载。
根据规范,您既不能更改方法的返回类型,也不能更改参数类型。其他语言支持所谓的共变量返回类型或反变量参数类型,但C#不支持。
您可以做的是使用接口和显式实现:
interface IInterface
{
object GetValue(object parameter);
}
abstract class MyAbstractClass<T> : IInterface where T : class
{
public T GetValue(T parameter)
{
// ...
}
object IInterface.GetValue(object parameter) => GetValue(parameter as T);
}
...然后使用界面:
public static void Main(string[] args)
{
IList<IInterface> list = new List<IInterface>();
list.Add(new MyImpClass());
list[0].GetValue("Testing...");
}
答案 3 :(得分:1)
只需将您的基本方法设为虚拟并在泛型类中覆盖它。
abstract class MyAbstractClass
{
public virtual object GetValue(object parameter)
{
Console.WriteLine("Hello from object");
return parameter;
}
}
abstract class MyAbstractClass<T> : MyAbstractClass
{
public override object GetValue(object parameter)
{
return GetValue((T)parameter);
}
public T GetValue(T parameter)
{
Console.WriteLine("Hello from generics");
return parameter;
}
}