C# 从AbstractClass调用方法<;T>;处理AbstractClass的实例
假设我有一个抽象类,比如:C# 从AbstractClass调用方法<;T>;处理AbstractClass的实例,c#,.net,generics,C#,.net,Generics,假设我有一个抽象类,比如: abstract class MyAbstractClass { public object GetValue(object parameter) { Console.WriteLine("Hello from object"); return parameter; } } 另外,我还有一个抽象类扩展了MyAbstractClass: abstract class MyAbstractClass<T>
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;
}
}
现在,我声明了一个MyAbstractClass
的列表(没有泛型类型),添加了MyImpClass
的一个实例,并调用您的GetValue
方法
public static void Main(string[] args)
{
IList<MyAbstractClass> list = new List<MyAbstractClass>();
list.Add(new MyImpClass());
list[0].GetValue("Testing...");
}
我这样做是因为在应用程序的某些部分,我需要接收MyAbstractClass
的实例,而不管泛型类型参数是什么。因此,我使用MyAbstractClass
来实现这一点
我的问题是:有没有一种方法可以从MyAbstractClass
中调用该方法,并遍历MyAbstractClass
的列表
我希望我已经说得够清楚了。谢谢。使
公共对象GetValue(对象参数)
虚拟化
,并在通用版本中覆盖它
像这样:
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> { }
它产生以下输出:
来自对象的您好来自泛型的你好 这似乎是OP最终想要代码做的事情;迭代基类型的集合,如果实例是泛型的,则调用泛型方法
将问题具体解释为要求直接调用方法的泛型版本,对我来说似乎忽略了一个X/Y问题。只需将基本方法虚拟化并在泛型类中重写它即可
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;
}
}
抽象类MyAbstractClass
{
公共虚拟对象GetValue(对象参数)
{
WriteLine(“来自对象的你好”);
返回参数;
}
}
抽象类MyAbstractClass:MyAbstractClass
{
公共覆盖对象GetValue(对象参数)
{
返回GetValue((T)参数);
}
公共T GetValue(T参数)
{
WriteLine(“来自泛型的你好”);
返回参数;
}
}
要直接调用通用调用,您需要强制转换它:
(list[0] as MyAbstractClass<string>)?.GetValue("Testing...");
public override object GetValue(object parameter) => GetValue((T)parameter);
MyAbstractClass
的方法更改为虚拟:
public virtual object GetValue(object parameter)
以这种方式,你想要实现的目标是不可能的。这将要求您重写该方法,但您要做的是添加第二个方法,称为重载 根据规范,您既不能更改方法的返回类型,也不能更改参数类型。其他语言支持所谓的协变返回类型或逆变参数类型,但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);
}
接口界面
{
对象GetValue(对象参数);
}
抽象类MyAbstractClass:I接口,其中T:class
{
公共T GetValue(T参数)
{
// ...
}
object IInterface.GetValue(对象参数)=>GetValue(参数为T);
}
…然后使用接口:
public static void Main(string[] args)
{
IList<IInterface> list = new List<IInterface>();
list.Add(new MyImpClass());
list[0].GetValue("Testing...");
}
publicstaticvoidmain(字符串[]args)
{
IList list=新列表();
添加(新的MyImpClass());
列表[0]。GetValue(“测试…”);
}
刚刚认识到,返回类型不相同签名不相同时无法重写。子类上需要两个方法,一个是泛型类型,另一个是封装泛型版本的重写。我给你举个例子。@Servy这是一种非常迂腐的解释问题的方式。泛型版本在我的代码中被调用,它只是首先通过非泛型版本。@Servy-Question说我的问题是:有没有一种方法可以从MyAbstractClass迭代MyAbstractClass列表中调用该方法?-一种让它调用泛型的方法——不管调用什么,我不明白为什么使用接口比使用抽象类更可取,尽管问题可能不共享整个场景,所以OP可能实际上需要类而不是接口它在理论上编译,因为我添加了“where t:class”。它没有编译,因为我没有返回任何内容。我也没有说使用接口更好。其他解决方案当然也是可行的。在我看来,使用接口是这里的一项要求。做一个抽象类重载一个已经实现的抽象类…哦,头痛已经开始了。接口允许您更改实现(这是您的要求),而无需所有这些古怪的东西。您的答案基本上与我的答案相同,它工作正常,并且完全符合OP的要求。我不知道我的回答有什么问题。我不认为这不能回答这个问题。@BradleyUffner-同意。。。起初,你的答案在IMO上不见了,这就是为什么我贴了我的。至于实际被问到的问题——我认为这并不是真正关于调用派生类的泛型或非泛型(我的问题是:有没有一种方法可以从MyAbstractClass迭代MyAbstractClass的列表来调用该方法?…),而是让它真正起作用…@GiladGreen谢谢你的回答。它帮助我解决了这个具体案件。但不幸的是,当我试图将此解决方案应用于我的整个代码库时,我注意到这对没有参数的方法不起作用。我在这本书中再现了这个场景。这给了我一个错误当我重写方法public virtual object GetValue()
时,已经用相同的参数类型定义了一个名为“GetValue”的成员。你知道这种情况的解决方案吗?@Brunopers-不能用这种方式。你可以改用界面,但你现在问的问题实际上与贴出的问题不同。。。
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);
}
}
public override object GetValue(object parameter) => GetValue((T)parameter);
public virtual object GetValue(object parameter)
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...");
}