我想创建一个返回类型为ObservableCollection<T>^
的集合的泛型函数。调用者为类型参数T
传递托管类类型。
这是我对泛型函数的尝试之一,在对其他类的解释之后使用:
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems(AnimalType animalType, int count)
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
for (int i = 0; i < count; i++)
{
if (animalType == Dog)
{
CDog^ dog = gcnew CDog(i, count - i);
//CAnimal^ dog = gcnew CDog(i, count - i);
//T dog = gcnew CDog(i, count - i);
//T^ dog = gcnew CDog(i, count - i);
animals->Add(dog);
}
//else if (animalType == Cat) { ... }
//...
}
return animals;
}
因为我尝试了近1632种方法来使该功能正常工作,我无法告诉你为什么我按原样实现它: - /
班级CAnimal
是 CDog
的基类(假设还有更多动物)。 AnimalType
是一个枚举,旨在用于上述函数,以确定用于实例化和添加到集合的正确类类型:
ref class CAnimal
{
public:
CAnimal(){}
CAnimal(int _age) { age = _age; }
int age;
};
ref class CDog : CAnimal {
public:
CDog(){}
CDog(int _age, int _other)
:CAnimal(age), other(_other) {}
int other;
};
enum AnimalType
{
Dog,
Cat,
Fish,
// ...
};
此外,有一个家长班持有ObservableCollection
的狗,猫等等:
ref class CZoo
{
private:
ObservableCollection<CDog^>^ dogs;
public:
CZoo()
{
dogs = GetItems<CDog^>(AnimalType::Dog, 3);
}
};
编译器抛出以下错误:
错误C2670:'System :: Collections :: ObjectModel :: Collection :: Add': 函数模板无法从类型'CDog ^'
转换参数1
你能告诉我我做错了吗?
!!!解决方案!!!
基于David Yaws' answer我最终将构造函数参数移动到名为Initialize
的新函数中,并删除了enum AnimalTypes
。最终代码更改为以下内容:
ref class CAnimal
{
internal:
virtual void Initialize(int _age, int _other)
{
age = _age;
other = _other;
}
public:
int age;
int other;
};
ref class CDog : CAnimal {};
ref class CCat : CAnimal {};
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems(int count)
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
for (int i = 0; i < count; i++)
{
T animal = gcnew T();
animal->Initialize(i, count - i);
animals->Add(animal);
}
return animals;
}
ref class CZoo
{
private:
ObservableCollection<CDog^>^ dogs;
ObservableCollection<CCat^>^ cats;
public:
CZoo()
{
dogs = GetItems<CDog^>(3);
cats = GetItems<CCat^>(7);
}
};
答案 0 :(得分:1)
如果我删除与错误无关的内容,这就是我们所拥有的内容:
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems()
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
animals->Add(gcnew CDog());
return animals;
}
现在,如果将其作为GetItems<CCat^>()
调用,会发生什么?现在,您尝试将CDog
放入CCat
列表中,但这不起作用。这就是错误消息所说的内容:CDog
可能无法转换为T
。
如果你想这样做,有几种可能的解决方案:
CAnimal
的列表。 CDog
始终有效,可以放入CAnimal
。T
。我推荐后者,并做这样的事情:
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems(int count)
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
for (int i = 0; i < count; i++)
{
T animal = gcnew T();
animal->Initialize(i, count-i);
animals->Add(animal);
}
return animals;
}
gcnew()
约束,这意味着该类有一个零参数构造函数,你可以使用T
类型来调用它。CAnimal
上定义的方法中。这样您就可以在任何T
上调用它。GetItems<CDog^>(AnimalType::Cat, 3)
之类的内容。