Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从AbstractClass调用方法<;T>;处理AbstractClass的实例_C#_.net_Generics - Fatal编程技术网

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...");
    }