C# C中的模板函数和类型#

C# C中的模板函数和类型#,c#,template-function,C#,Template Function,您好,由于所涉及的类型,我在设置类时遇到了一些困难。 以下是想法: 类A有一个私有的arraylist,它应该由类B的实例填充。 因此,类A的任何实例都将在类B元素的ArrayList上具有其属性。 类A有一个函数可以向其ArrayList中添加一个新的B实例。更具体地说,在A.add中,新的B被实例化、初始化,然后添加到ArrayList中。 类B是一个非常简单的类:其中有一个枚举类型,还应该包含对外部对象/类或其他对象的引用。 假设有类*appleClass、peachClass、lemon

您好,由于所涉及的类型,我在设置类时遇到了一些困难。 以下是想法:

类A有一个私有的arraylist,它应该由类B的实例填充。 因此,类A的任何实例都将在类B元素的ArrayList上具有其属性。 类A有一个函数可以向其ArrayList中添加一个新的B实例。更具体地说,在A.add中,新的B被实例化、初始化,然后添加到ArrayList中。 类B是一个非常简单的类:其中有一个枚举类型,还应该包含对外部对象/类或其他对象的引用。 假设有类*appleClass、peachClass、lemonClass*,类B是水果类,类A是水果篮。每当主代码看到一个水果时,它应该要求类a将其添加到篮子中。这意味着,A.add(thisfruit),但该水果可能是任何水果类。这反过来意味着我需要一个通用签名来实例化classB,并将其添加到a.arraylist中。我不知道;我不知道我是否有道理,但我也会尝试给出一些代码来解释我的问题

class Lemon
{
    //....
}
class Apple
{
    //....
}
class Peach
{
    //....
}

class Fruit
{
    public int color;
    <T> fruit;///this should be the <T> type depending on the fruit class i am adding
    public Fruit(T f, int c){fruit = f; color = c;}
}

class Basket
{
    ArrayList FruitArray= new ArrayList();
    public void AddFruit<T>(T f,int c )
    {
        fru = new Fruit(f,c);
        FruitArray.Add(fru);
    }
}
class柠檬
{
//....
}
苹果类
{
//....
}
桃子类
{
//....
}
等级水果
{
公共int颜色;
水果;///这应该是我添加的水果类的类型
公共水果(tf,intc){Fruit=f;color=c;}
}
班级篮
{
ArrayList水果数组=新的ArrayList();
公共空间(T f,int c)
{
fru=新果实(f,c);
添加(fru);
}
}
不知何故,我应该使用模板??我知道上面的代码是错误的,但我不知道如何最好地做到这一点

多谢各位

亚历克斯

编辑
谢谢大家的回答。它们似乎都指向使用基类/抽象类结果,并从中派生出特定的结果。我很抱歉地告诉你,我的实际项目不涉及水果,我只是简单地使用它们。实际的项目是在Unity中,其中somr的“果实”来自Unity课程,其他一些“果实”是我自己的课程。这意味着我不能为来自Unity命名空间的类声明父类。我更希望能够有一个对“水果”的泛型引用,这将是旧C语言中的一个空指针。我知道C#是强类型的,不允许大多数类似指针的用法,但必须有一种传递“未知”的方法将对象引用到类/函数并稍后使用/解析…

编辑以反映问题中的新信息: ArrayList是一种很好的方法,但我不会在这种情况下使用泛型,因为它会导致很多麻烦和代码重复。相反,我将使用反射在运行时查找并调用正确的重载。一段代码胜过千言万语,下面是一个简单的控制台应用程序:

class ObjectA {
    public int A { get; set; }
    public ObjectA( int a ) {
        this.A = a;
    }
}

class ObjectB {
    public int B { get; set; }
    public ObjectB( int b ) {
        this.B = b;
    }
}

class ObjectC {
    public int C { get; set; }
    public ObjectC( int c ) {
        this.C = c;
    }
}

class DynamicOverloadResolution {
    ArrayList items;

    public DynamicOverloadResolution( ) {
        items = new ArrayList( ) { 
            new ObjectA( 1 ), new ObjectB( 2 ), new ObjectC( 3 )
        };
    }

    public void ProcessObjects( ) {
        foreach ( object o in items )
            processObject( o );
    }

    private void processObject( object o ) {
        Type t = typeof( DynamicOverloadResolution );
        IEnumerable<MethodInfo> processMethods = t.GetMethods( )
            .Where( m => m.Name == "process" );

        foreach(MethodInfo info in processMethods) {
            if ( info.GetParameters( ).First( ).ParameterType == o.GetType( ) )
                info.Invoke( this, new object[ ] { o } );
        }
    }

    public void process( ObjectA a ) { Console.WriteLine( a.A ); }
    public void process( ObjectB b ) { Console.WriteLine( b.B ); }
    public void process( ObjectC c ) { Console.WriteLine( c.C ); }
}

class Program {
    static void Main( string[ ] args ) {
        var d = new DynamicOverloadResolution( );
        d.ProcessObjects( );
    }
}
旧答案:

您可以简单地将fruit设置为抽象类或接口,让所有内容继承/实现它,并保留fruit列表:

interface IFruit {
    public int c { get; set; }
}

class Apple : IFruit { }
class Peach : IFruit { }
class Lemon : IFruit { }

class Basket {
    List<IFruit> fruitList = new List<IFruit>();

    public void AddIFruit<T>(int c) 
        where T : IFruit, new {

        var f = new T();
        f.c = c;
        fruitList.Add(f);
    }
}
或者,您可以使用该运算符将IFruit转换为它的一个实现(注意,如果转换不可能,则结果将为null,即您使用了错误的类型):

Lista=Basket.GetFruits();
开关(a[0].c){
案例0:
柠檬L=a[0]作为柠檬;
}

但是如果您需要这样做,那么您可能是从错误的角度处理问题。

编辑以反映问题中的新信息: ArrayList是一种很好的方法,但我不会在这种情况下使用泛型,因为它会导致很多麻烦和代码重复。相反,我将使用反射在运行时查找并调用正确的重载。一段代码胜过千言万语,下面是一个简单的控制台应用程序:

class ObjectA {
    public int A { get; set; }
    public ObjectA( int a ) {
        this.A = a;
    }
}

class ObjectB {
    public int B { get; set; }
    public ObjectB( int b ) {
        this.B = b;
    }
}

class ObjectC {
    public int C { get; set; }
    public ObjectC( int c ) {
        this.C = c;
    }
}

class DynamicOverloadResolution {
    ArrayList items;

    public DynamicOverloadResolution( ) {
        items = new ArrayList( ) { 
            new ObjectA( 1 ), new ObjectB( 2 ), new ObjectC( 3 )
        };
    }

    public void ProcessObjects( ) {
        foreach ( object o in items )
            processObject( o );
    }

    private void processObject( object o ) {
        Type t = typeof( DynamicOverloadResolution );
        IEnumerable<MethodInfo> processMethods = t.GetMethods( )
            .Where( m => m.Name == "process" );

        foreach(MethodInfo info in processMethods) {
            if ( info.GetParameters( ).First( ).ParameterType == o.GetType( ) )
                info.Invoke( this, new object[ ] { o } );
        }
    }

    public void process( ObjectA a ) { Console.WriteLine( a.A ); }
    public void process( ObjectB b ) { Console.WriteLine( b.B ); }
    public void process( ObjectC c ) { Console.WriteLine( c.C ); }
}

class Program {
    static void Main( string[ ] args ) {
        var d = new DynamicOverloadResolution( );
        d.ProcessObjects( );
    }
}
旧答案:

您可以简单地将fruit设置为抽象类或接口,让所有内容继承/实现它,并保留fruit列表:

interface IFruit {
    public int c { get; set; }
}

class Apple : IFruit { }
class Peach : IFruit { }
class Lemon : IFruit { }

class Basket {
    List<IFruit> fruitList = new List<IFruit>();

    public void AddIFruit<T>(int c) 
        where T : IFruit, new {

        var f = new T();
        f.c = c;
        fruitList.Add(f);
    }
}
或者,您可以使用该运算符将IFruit转换为它的一个实现(注意,如果转换不可能,则结果将为null,即您使用了错误的类型):

Lista=Basket.GetFruits();
开关(a[0].c){
案例0:
柠檬L=a[0]作为柠檬;
}
但是如果你需要这样做,那么你可能从一个错误的角度来处理这个问题。

C#没有模板,但它确实有,这是一个类似的概念。您非常接近,但是您的
Fruit
类根本不需要是泛型的。只需确保所有
Lemon
Apple
Peach
类都继承自
Fruit

class Fruit
{
    public int color;
    public Fruit() { } // default constructor for generic constrain below
}
class Lemon : Fruit
{
    //....
    public Lemon() : base() { } 
}
class Apple : Fruit
{
    //....
    public Apple() : base() { } 
}
class Peach : Fruit
{
    //....
    public Peach() : base() { } 
}
现在,您可以使用如下方法设计
篮子
类:

class Basket
{
    List<Fruit> FruitList = new List<Fruit>();

    public void AddFruit<T>(int c) where T : Fruit, new()
    {
        fru = new T();
        fru.color = c;
        FruitList.Add(fru);
    }
}

Basket basket = new Basket();
basket.Add<Apple>(2);
类篮
{
列表结果列表=新列表();
公共无效添加水果(int c),其中T:水果,新()
{
fru=新的T();
fru.color=c;
结果列表。添加(fru);
}
}
篮子=新篮子();
增加(2);
C#没有模板,但它确实有,这是一个类似的概念。您非常接近,但是您的
Fruit
类根本不需要是泛型的。只需确保所有
Lemon
Apple
Peach
类都继承自
Fruit

class Fruit
{
    public int color;
    public Fruit() { } // default constructor for generic constrain below
}
class Lemon : Fruit
{
    //....
    public Lemon() : base() { } 
}
class Apple : Fruit
{
    //....
    public Apple() : base() { } 
}
class Peach : Fruit
{
    //....
    public Peach() : base() { } 
}
现在,您可以使用如下方法设计
篮子
类:

class Basket
{
    List<Fruit> FruitList = new List<Fruit>();

    public void AddFruit<T>(int c) where T : Fruit, new()
    {
        fru = new T();
        fru.color = c;
        FruitList.Add(fru);
    }
}

Basket basket = new Basket();
basket.Add<Apple>(2);
类篮
{
列表结果列表=新列表();
公共无效添加水果(int c),其中T:水果,新()
{
fru=新的T();
fru.color=c;
结果列表。添加(fru);
}
}
篮子=新篮子();
增加(2);
在C#中,它们被称为泛型方法而不是模板方法,因为它们不是在编译时每次生成的

至于你的例子:

class Lemon : Fruit
{
    public Lemon(int c = 0) : base(c){}
    //....
}
class Apple : Fruit
{
    public Apple (int c = 0) : base(c){}
    //....
}
class Peach : Fruit
{
    public Peach (int c = 0) : base(c){}
    //....
}

class Fruit
{
    public int color;
    public Fruit(int c){ color = c; }
}

class Basket
{
    List<Fruit> fruits = new List<Fruit>();

    public void AddFruit(Fruit f)
    {
        fruits.Add(f);
    }

    public void CreateFruit<T>(int c) : where T : Fruit
    {
        Fruit f = Activator.CreateInstance<T>() as Fruit;
        f.color = c;
        fruits.Add(f);
    }
}
柠檬类:水果
{
公共柠檬(int c=0):碱(c){
//....
}
苹果类:F