C#-即使在正确的泛型约束之后,堆栈推送操作也不起作用 名称空间控制台ap3 { 班级计划 { //主方法-程序的入口点 静态void Main(字符串[]参数) { var=newstack(); 动物清洁剂(动物); } } //声明和继承的简单类。 公营动物{} 公共类熊:动物{} 公营骆驼:动物{} 公共类堆栈//基本堆栈实现 { 内部位置; T[]数据=新的T[100]; 公共无效推送(T obj)=>数据[position++]=obj; 公共T Pop()=>数据[--位置]; } 公营动物园清洁工 { 公共静态空隙冲洗(堆叠动物),其中T:动物 { //为什么我不能这样做?我已经正确地指出“T”可以 //属于动物类型或可以衍生动物,但这 //仍然会导致编译错误! Push(new Animal());//错误:无法从“Animal”转换为类型T!! Push(new Bear());//错误:无法从'Bear'转换为类型T!! } } }
问题: 在Wash()方法中,我正确地将泛型参数“T”设置为“Animal”类型或可以从“Animal”派生。那么为什么我不能做推送操作来插入动物或熊的物体呢C#-即使在正确的泛型约束之后,堆栈推送操作也不起作用 名称空间控制台ap3 { 班级计划 { //主方法-程序的入口点 静态void Main(字符串[]参数) { var=newstack(); 动物清洁剂(动物); } } //声明和继承的简单类。 公营动物{} 公共类熊:动物{} 公营骆驼:动物{} 公共类堆栈//基本堆栈实现 { 内部位置; T[]数据=新的T[100]; 公共无效推送(T obj)=>数据[position++]=obj; 公共T Pop()=>数据[--位置]; } 公营动物园清洁工 { 公共静态空隙冲洗(堆叠动物),其中T:动物 { //为什么我不能这样做?我已经正确地指出“T”可以 //属于动物类型或可以衍生动物,但这 //仍然会导致编译错误! Push(new Animal());//错误:无法从“Animal”转换为类型T!! Push(new Bear());//错误:无法从'Bear'转换为类型T!! } } },c#,generics,stack,generic-constraints,C#,Generics,Stack,Generic Constraints,问题: 在Wash()方法中,我正确地将泛型参数“T”设置为“Animal”类型或可以从“Animal”派生。那么为什么我不能做推送操作来插入动物或熊的物体呢 为什么animals.Push(新动物());动物。推(新熊)()导致编译错误?这是正常的,也是预期的。如果您有一个堆栈,其中T:Animal,那么您必须想象T可能类似于Giraffe。唯一可以推压堆栈的东西是长颈鹿或长颈鹿(aMasaiGiraffe,aNubianGiraffe,等等)。你不能推一只熊或一只动物:它必须是长颈鹿(或更好
为什么
animals.Push(新动物());动物。推(新熊)()代码>导致编译错误?这是正常的,也是预期的。如果您有一个堆栈,其中T:Animal
,那么您必须想象T
可能类似于Giraffe
。唯一可以推压堆栈的东西是长颈鹿
或长颈鹿
(aMasaiGiraffe
,aNubianGiraffe
,等等)。你不能推一只熊
或一只动物
:它必须是长颈鹿
(或更好)
对于T
,这意味着您可以推送T
——可能是newt()
(通过T:new()
约束)
如果您希望能够推送任何动物
:不要在t:Animal
的位置使用堆栈-使用堆栈
欢迎使用C。这是C#编译器的一个非常恼人的限制。您可能期望它在任何其他语言中都能工作,因为它在OOP范式中是有意义的
OP我希望您知道,在C#中已经有了堆栈的实现。如果它与不接受继承的类型有相同的问题,那么您可以使用包含此泛型项的包装器。这很痛苦,但你选择了CS
所以你得做些变通。这也不是一个有趣的解决办法。这是:
>公共类堆栈
{
public int position=>data.Count-1;
IList数据=新列表();
公共无效推送(T obj)=>数据添加(obj);
公共广播电台
{
var ret=数据[位置];
数据删除(位置);
返回ret;
}
公共重写字符串ToString()
{
返回$“元素数:{data.Count}.{data}”;
}
}
>公营动物{}
公共类熊:动物{}
公营骆驼:动物{}
>var sta=新堆栈();
sta.Push(新动物());
sta.推(新轴承());
sta.Push(新骆驼());
>sta
[元素数量:3.系统.集合.通用.列表'1[提交#1+动物]]
>而(sta.position>=0)
{
var x=sta.Pop();
WriteLine($”弹出的元素类型:{x.GetType()}”);
}
弹出元素类型:提交#3+驼峰
弹出元素类型:提交#2+熊
弹出元素类型:提交#1+动物
如果任何C#genius有更好的解决方法,请告诉我,因为这是一个非常恼人的泛型限制。泛型应该像其他语言一样允许继承类。不,您不希望它工作。OP的方法采用堆栈
,其中T
是动物
。因此可以使用Wash(新堆栈)调用它
在这种情况下,尝试推送熊
或动物
将是一个错误。因为熊和动物都不是骆驼。
namespace ConsoleApp3
{
class Program
{
// Main method - entry point of program
static void Main(string[] args)
{
var animals = new Stack<Animal>();
ZooCleaner.Wash(animals);
}
}
//Simple classes declared and inherited.
public class Animal { }
public class Bear : Animal{ }
public class Camel : Animal { }
public class Stack<T> //Basic stack implementation
{
int position;
T[] data = new T[100];
public void Push(T obj) => data[position++] = obj;
public T Pop() => data[--position];
}
public class ZooCleaner
{
public static void Wash<T>(Stack<T> animals) where T:Animal
{
//Why I cannot do this? I have correctly stated that 'T' can
//be of type Animal or can derive Animal but this
//still causes compilation error!
animals.Push(new Animal()); //Error: Cannot convert from 'Animal' To Type T!!
animals.Push(new Bear()); //Error: Cannot convert from 'Bear' To Type T!!
}
}
}