我正在开发一款有趣的小游戏,我偶然发现了一个令人困惑的时刻,C#是运营商。这是代码:
public static InventorySlot FindSlotWithItem(this IInventory inventory, Type itemType)
{
return inventory.InventorySlots.FirstOrDefault(t => t is itemType);
}
目前,这段代码没有编译,因为我的Visual Studio告诉我类型或命名空间名称' itemType'无法找到。我想知道为什么会这样,并在MSDN上寻找一些信息。这就是我发现的:
是(C#参考): 检查对象是否与给定类型兼容。例如,以下代码可以确定对象是MyObject类型的实例,还是从MyObject派生的类型
这些线让我更加困惑,因为我明确地将一个对象作为第一个参数传递,而将类型作为第二个参数传递。我知道这与编译器查找名为' itemType'的类型有关,但这并不是我想要的行为。
请告诉我为什么这样的语法不起作用以及为什么' itemType'不被视为'是'操作
答案 0 :(得分:6)
这里的问题是Type
类的对象与类的编译时常量引用不同。相反,Type
对象只是封装类的元数据的对象,因此它们不能用于直接创建变量,调用静态成员,作为泛型传递,或者使用is
调用实际的类引用的方式。
话虽如此,上述所有操作都只使用了元数据。对于类型比较,请尝试
t => itemType.IsAssignableFrom(t.GetType());
这将检查"类型itemType
的变量是否可以赋值t.GetType()
" - 它不仅可以检查打字,还可以很好地接受多态类型而无需投诉。
答案 1 :(得分:5)
你可以这样做:
public static InventorySlot FindItem<T>(this IInventory inventory)
{
return inventory.InventorySlots.FirstOrDefault(t => t is T);
}
或者这个:
public static InventorySlot FindItem(this IInventory inventory, Type itemType)
{
return inventory.InventorySlots.FirstOrDefault(t => itemType.IsAssignableFrom(t.GetType()));
}
答案 2 :(得分:2)
您无法像这样检查对象的类型,您必须使用运营商的类型名称:
// doesn't work
t is itemType
//working
t is String
因此,正如@AmirPopovich建议的那样,您可以使用通用方法,它可以帮助您为is
运算符提供类型:
public static InventorySlot FindItem<T>(this IInventory inventory)
{
return inventory.InventorySlots.FirstOrDefault(t => t is T);
}