C# 检查对象是否是父对象的转换子对象
C# Check if Object is a casted child of parent object
我真的无法解释得更好,但我会给你一个我的案例的例子:
我有一个名为 "Item" 的 class 类型
Item 有一个子 class 继承了它,叫做 "Weapon"
Weapon 有一个名为 "RangedWeapon"
的子class
现在我的玩家可以随意交换和使用物品,但由于它们都是物品,我不是在寻找错误,所以玩家装备的所有物品都显示为物品class。因此,如果我装备了一把远程武器,例如一把枪,在我的玩家脚本中它仍将被视为一个物品,我将只能访问物品具有的属性,而不能访问 RangedWeapon 的附加属性。我的问题是,如果我有一个 Item 对象,我该如何检查它最初是 Weapon 还是 RangedWeapon?
如果有什么不明白的地方请问我,我会进一步解释。
感谢您的所有评论:)
编辑
代码示例:
假设我有一个名为 gun 的 RangedWeapon 对象。
RangedWeapon gun = new RangedWeapon(*parameters here*);
在我的播放器脚本中,我有一个存储当前持有物品的物品值:
//Some stuff above
private Item heldItem;
//etc
每当我装备一个物品时,该物品就会存储在 "heldItem" 变量中。
所以如果我要装备枪,就会发生这种情况:
heldItem = gun;
现在这段代码是有效的,因为 gun 是一个 RangedWeapon 并且 RangedWeapon 继承自 Item,但是如果我不知道我装备的是什么物品以及它最初是 Item、Weapon 还是 RangedWeapon 怎么办?如何通过 heldItem 检索其原始类型?
例如:
如果我可以做类似的事情(为了示例,这完全是一个伪代码)
if (typeof(heldItem) was RangedWeapon) {//stuff}
else if (typeof(heldItem) was Weapon) {//stuff}
希望我说得更清楚:)
注:
@RufusL 回答了这个问题我只是将其作为答案发布,而不是作为评论发布,以便更容易看到。
解决方案是简单地使用 is
运算符。
我引用:
if (item is RangedWeapon) { RangedWeapon rw = (RangedWeapon) item; //
access RangedWeapon properties of rw here }
解决此问题的另一种方法是在项目列表中使用 interface
而不是 class
。接口很好,因为它们定义了一个契约——一组保证存在的 public 方法和属性,但是 classes 本身定义了实现。
List<Item>
的问题是列表的所有成员都向下转换(不确定这是否是正确的术语)到 Item
,只有基数 class 将调用任何常用方法的实现。
通过接口,列表中的每个对象都保留了其特定类型的实现,因此我们可以在调用相同方法时从不同类型的对象获得不同的结果。
这是一个例子,它可能不是最好的,但我认为它说明了这一点:
// This interface defines the public members that we want to access from any Item
public interface IItem
{
string Name { get; set; }
void Click();
}
// This class may be a base class for other items, but it's *NOT* a base class for
// Weapon. Instead, Weapon will implement a common interface with other items
public class Item : IItem
{
public string Name { get; set; } = "Item";
public void Click()
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine($"{Name} was selected!");
Console.ResetColor();
}
}
// Here we have Weapon as a base class that implements the IItem interface,
// (and contains the default implementation for sub classes)
public class Weapon : IItem
{
public string Name { get; set; } = "Weapon";
public void Click()
{
Console.ForegroundColor = FireColor;
Console.WriteLine($"{Name} was fired!");
Console.ResetColor();
}
// FireColor is protected, meaning it's only available to
// this class and classes that derive from this class
protected ConsoleColor FireColor { get; set; } = ConsoleColor.Red;
}
// Now we have a class that derives from the Weapon
// base class, and changes the Name property
public class Pistol : Weapon
{
public Pistol()
{
Name = "Pistol";
}
}
// And an additional class that derives from
// Weapon, which changes both Name and FireColor
public class RangedWeapon : Weapon
{
public RangedWeapon()
{
FireColor = ConsoleColor.Yellow;
Name = "Ranged Weapon";
}
}
现在,当我们想要一个项目集合时,我们创建一个实现 IItem
接口的对象集合,而不是一个特定的、具体的 class。这样我们得到了所有常用方法,但是实际 class 类型的行为:
private static void Main()
{
// Add three unique objects that implement 'IItem' to a list
var items = new List<IItem>
{
new Item(),
new Pistol(),
new RangedWeapon()
};
// Call the 'Click' method for each 'IItem' object
items.ForEach(item => item.Click());
GetKeyFromUser("\nDone! Press any key to exit...");
}
输出
请注意,在输出中我们为每个项目设置了不同的颜色,并且 Item
和 Weapon
之间的文本不同(即 "selected"
与 "fired"
) ,并且每个项目都显示它是唯一的 Name
。此外,手枪使用 base-class 实现 FireColor
(红色),而 RangedWeapon
实现了它自己的颜色。
我真的无法解释得更好,但我会给你一个我的案例的例子:
我有一个名为 "Item" 的 class 类型 Item 有一个子 class 继承了它,叫做 "Weapon" Weapon 有一个名为 "RangedWeapon"
的子class现在我的玩家可以随意交换和使用物品,但由于它们都是物品,我不是在寻找错误,所以玩家装备的所有物品都显示为物品class。因此,如果我装备了一把远程武器,例如一把枪,在我的玩家脚本中它仍将被视为一个物品,我将只能访问物品具有的属性,而不能访问 RangedWeapon 的附加属性。我的问题是,如果我有一个 Item 对象,我该如何检查它最初是 Weapon 还是 RangedWeapon?
如果有什么不明白的地方请问我,我会进一步解释。
感谢您的所有评论:)
编辑
代码示例:
假设我有一个名为 gun 的 RangedWeapon 对象。
RangedWeapon gun = new RangedWeapon(*parameters here*);
在我的播放器脚本中,我有一个存储当前持有物品的物品值:
//Some stuff above
private Item heldItem;
//etc
每当我装备一个物品时,该物品就会存储在 "heldItem" 变量中。 所以如果我要装备枪,就会发生这种情况:
heldItem = gun;
现在这段代码是有效的,因为 gun 是一个 RangedWeapon 并且 RangedWeapon 继承自 Item,但是如果我不知道我装备的是什么物品以及它最初是 Item、Weapon 还是 RangedWeapon 怎么办?如何通过 heldItem 检索其原始类型?
例如: 如果我可以做类似的事情(为了示例,这完全是一个伪代码)
if (typeof(heldItem) was RangedWeapon) {//stuff}
else if (typeof(heldItem) was Weapon) {//stuff}
希望我说得更清楚:)
注:
@RufusL 回答了这个问题我只是将其作为答案发布,而不是作为评论发布,以便更容易看到。
解决方案是简单地使用 is
运算符。
我引用:
if (item is RangedWeapon) { RangedWeapon rw = (RangedWeapon) item; // access RangedWeapon properties of rw here }
解决此问题的另一种方法是在项目列表中使用 interface
而不是 class
。接口很好,因为它们定义了一个契约——一组保证存在的 public 方法和属性,但是 classes 本身定义了实现。
List<Item>
的问题是列表的所有成员都向下转换(不确定这是否是正确的术语)到 Item
,只有基数 class 将调用任何常用方法的实现。
通过接口,列表中的每个对象都保留了其特定类型的实现,因此我们可以在调用相同方法时从不同类型的对象获得不同的结果。
这是一个例子,它可能不是最好的,但我认为它说明了这一点:
// This interface defines the public members that we want to access from any Item
public interface IItem
{
string Name { get; set; }
void Click();
}
// This class may be a base class for other items, but it's *NOT* a base class for
// Weapon. Instead, Weapon will implement a common interface with other items
public class Item : IItem
{
public string Name { get; set; } = "Item";
public void Click()
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine($"{Name} was selected!");
Console.ResetColor();
}
}
// Here we have Weapon as a base class that implements the IItem interface,
// (and contains the default implementation for sub classes)
public class Weapon : IItem
{
public string Name { get; set; } = "Weapon";
public void Click()
{
Console.ForegroundColor = FireColor;
Console.WriteLine($"{Name} was fired!");
Console.ResetColor();
}
// FireColor is protected, meaning it's only available to
// this class and classes that derive from this class
protected ConsoleColor FireColor { get; set; } = ConsoleColor.Red;
}
// Now we have a class that derives from the Weapon
// base class, and changes the Name property
public class Pistol : Weapon
{
public Pistol()
{
Name = "Pistol";
}
}
// And an additional class that derives from
// Weapon, which changes both Name and FireColor
public class RangedWeapon : Weapon
{
public RangedWeapon()
{
FireColor = ConsoleColor.Yellow;
Name = "Ranged Weapon";
}
}
现在,当我们想要一个项目集合时,我们创建一个实现 IItem
接口的对象集合,而不是一个特定的、具体的 class。这样我们得到了所有常用方法,但是实际 class 类型的行为:
private static void Main()
{
// Add three unique objects that implement 'IItem' to a list
var items = new List<IItem>
{
new Item(),
new Pistol(),
new RangedWeapon()
};
// Call the 'Click' method for each 'IItem' object
items.ForEach(item => item.Click());
GetKeyFromUser("\nDone! Press any key to exit...");
}
输出
请注意,在输出中我们为每个项目设置了不同的颜色,并且 Item
和 Weapon
之间的文本不同(即 "selected"
与 "fired"
) ,并且每个项目都显示它是唯一的 Name
。此外,手枪使用 base-class 实现 FireColor
(红色),而 RangedWeapon
实现了它自己的颜色。