C# C中的模板函数和类型#
您好,由于所涉及的类型,我在设置类时遇到了一些困难。 以下是想法: 类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中。我不知道;我不知道我是否有道理,但我也会尝试给出一些代码来解释我的问题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
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