Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.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# 在列表中的泛型函数中使用子类型<;家长>;对象_C#_Generics - Fatal编程技术网

C# 在列表中的泛型函数中使用子类型<;家长>;对象

C# 在列表中的泛型函数中使用子类型<;家长>;对象,c#,generics,C#,Generics,我的问题与我希望在泛型方法中使用子类型的方法类似,只是不调用该方法。例如: class Parent { } class Child1 : Parent { } class Child2 : Parent { } // could be other child classes, unknown to the Process class class Process { public Process() { List<Parent> L = new Li

我的问题与我希望在泛型方法中使用子类型的方法类似,只是不调用该方法。例如:

class Parent { }
class Child1 : Parent { }
class Child2 : Parent { }
// could be other child classes, unknown to the Process class

class Process
{
    public Process()
    {
        List<Parent> L = new List<Parent>();
        Child1 C1 = new Child1();
        Child2 C2 = new Child2();
        L.Add(C1);
        L.Add(C2);

        foreach(Parent P in L)
        {
            DoSomething(P);
        }
    }

    public void DoSomething<TypeP>(TypeP P)
    {
        // P is 'Child1', 'Child2' or potentially something else
        // TypeP is 'Parent'

        //TypeP = P.GetType(); //doesnt work
        //DoSomethingElse<P.GetType()>(); //doesnt work
        DoSomethingElse<TypeP>();
    }

    public void DoSomethingElse<T>()
    {
        // T is 'Parent'
        T R = Activator.CreateInstance<T>(); // want R to be 'Child1' or 'Child2'
    }
}
类父{}
类Child1:父{}
类Child2:父{}
//可能是流程类未知的其他子类
类进程
{
公共程序()
{
列表L=新列表();
Child1 C1=新的Child1();
Child2 C2=新的Child2();
L.加入(C1);
L.Add(C2);
foreach(父P在L中)
{
剂量测定法(P);
}
}
公共无效剂量测定(类型P)
{
//P是“Child1”、“Child2”或其他可能的词
//TypeP是“父级”
//TypeP=P.GetType();//不起作用
//DoSomethingElse();//不起作用
DoSomethingElse();
}
公共无效DoSomethingElse()
{
//T是“家长”
T R=Activator.CreateInstance();//希望R为'Child1'或'Child2'
}
}
我希望使用C1或C2类型而不是“父”类型来调用DoSomethingElse。我已经来过几次了,但找不到一个办法让它发挥作用。我觉得这应该是微不足道的,因为P是正确的类型

编辑:
DoSomethingElse之所以是泛型的,是因为可以从父类派生任意数量的子类。我以Child1和Child2为例,但实际上可能还有很多,因此DoSomethingElse中的switch语句不可行,因为派生类的数量未知。

上面的代码有几处错误。 泛型只适用于编译时已知的类型。在这里,我们将所有值向上转换为基类:

// L is a List<Parent>
L.Add(C1);
L.Add(C2);
现在我们可以使用带有约束的泛型,
TChild
应该从
Parent
派生:

public void DoSomething<TChild>(TChild P) where TChild : Parent
{    
    ...
    DoSomethingElse(P);
}

以下是

您可以使用is关键字检查类型:

public void DoSomething<TypeP>(TypeP P)
        {
            if (P is Child1)
            {

            }
            else if(P is Child2)
            {

            }
        }
public void DoSomething(类型P)
{
if(P是Child1)
{
}
else if(P为Child2)
{
}
}

这里有两个选项:

  • 在父类中将DoSomethingElse替换为虚拟方法,这样任何子类都必须覆盖所需的行为。然后,通常通过父类型实例(Liskov替换原则)调用被重写的方法。首选方式,伊姆霍

    public void DoSomething<TypeP>(TypeP P)
    {
        P.DoSomethingElse(); // this is virtual method to be overwritten by children types
    }
    
    public void DoSomething(类型P)
    {
    P.DoSomethingElse();//这是要被子类型覆盖的虚拟方法
    }
    
  • >P>“仿制药专业化”的方法(对于C我来说,它似乎有点不自然,因为C缺乏一些C++特性,但是……您可能会发现它合适)


    在您的特定情况下,您希望调用
    Activator.CreatInstance()
    ,但还有一种选择。有一个方法
    [Activator.CreatInstance(Type)][1]

    你可以通过稍微改变你的剂量测定方法来使用它

    public void DoSomethingElse(Parent p)
    {
        var R = Activator.CreateInstance(p.GetType());
    }
    

    当然,在不知道你在用它做什么的情况下,我不知道这是否一定有帮助。您可能仍然需要对R类型使用某种switch语句,然后才能使用这个新对象。但是,如果从这一点开始,您可以将
    R
    视为类型
    Parent
    ,那么这应该会对您有所帮助。

    使用dynamics或cast-as并检查是否为null?我觉得应该有人指出,这感觉有点错误,如果
    DoSomethingElse
    的类型参数是什么那么重要,也许这三种类型实际上不应该按它们的方式排列?看,它们不起作用的原因是因为泛型是编译时的事情-编译器决定如何调用泛型方法。这就是为什么在运行时尝试设置TypeP的类型是行不通的。由于您只知道运行时的类型,因此您的选项(假设您需要列表
    L
    作为
    list
    保留)几乎都是在运行时执行类型检查…@Leszek Repie将“DoSomething(P);”替换为“DoSomething(P作为动态);”似乎有效,尽管我不知道为什么在这个阶段子类的数量未知(因此泛型)。我已经做了一个编辑,希望能让它更清楚。@xareth更新了我的答案
    子类的数量未知(因此泛型)
    -这对我来说毫无意义,“数字未知”和“因此泛型”之间有什么联系?@Maarten也许我的逻辑不正确,但该方法是泛型的,因此它可以处理任何类型的“parent:child”类(只是键入使我认为它不正确)。使用泛型类型的真正原因是最终将其传递给Activator.CreateInstance(),谢谢Fabjan。我已经解决了它。结果我需要指定一个额外的泛型类型。因此“DoSomethingElse()”变成了“DoSomethingElse()”。一旦我更改了答案,您的答案最终就起作用了。
    public void DoSomething<TypeP>(TypeP P)
            {
                if (P is Child1)
                {
    
                }
                else if(P is Child2)
                {
    
                }
            }
    
    public void DoSomething<TypeP>(TypeP P)
    {
        P.DoSomethingElse(); // this is virtual method to be overwritten by children types
    }
    
    public void DoSomethingElse(Parent p)
    {
        var R = Activator.CreateInstance(p.GetType());
    }