簡體   English   中英

C# 檢查 Object 是否是父 object 的鑄造孩子

[英]C# Check if Object is a casted child of parent object

我真的無法更好地解釋這一點,但我會給你一個我的例子:

我有一個名為“Item”的 class 類型 Item 有一個繼承它的子類,稱為“Weapon”,Weapon 有一個名為“RangedWeapon”的子類

現在我的玩家可以隨意交換和使用物品,但由於它們都是物品,我不是在尋找錯誤,所以玩家裝備的所有物品都顯示為 Item class。 因此,如果我裝備遠程武器,例如槍,在我的播放器腳本中它仍將被視為物品,我將只能訪問物品的屬性,而不能訪問遠程武器的附加屬性。 我的問題是如果我有一個項目 object 我如何檢查它最初是武器還是遠程武器?

如果有不清楚的地方,請向我詢問,我會進一步解釋。

我感謝您的所有評論:)

編輯

代碼示例:

假設我有一個名為槍的遠程武器 object。

RangedWeapon gun = new RangedWeapon(*parameters here*);

在我的播放器腳本中,我有一個 Item 值,用於存儲當前持有的項目:

//Some stuff above

private Item heldItem;

//etc

每當我裝備一件物品時,該物品都會存儲在“heldItem”變量中。 因此,如果我要裝備槍,就會發生這種情況:

heldItem = gun;

現在這段代碼是有效的,因為 gun 是 RangedWeapon 並且 RangedWeapon 繼承自 Item,但是如果我不知道我裝備了什么物品以及它最初是 Item、Weapon 還是 RangedWeapon 怎么辦? 如何通過 holdItem 檢索其原始類型?

例如:如果我可以做類似的事情(為了示例,這完全是一個偽代碼)

if (typeof(heldItem) was RangedWeapon) {//stuff}
else if (typeof(heldItem) was Weapon) {//stuff}

希望我讓自己更清楚:)

解決此問題的另一種方法是在項目列表中使用interface而不是class 接口很好,因為它們定義了一個契約——一組保證存在的公共方法和屬性,但類本身定義了實現。

List<Item>的問題在於列表的所有成員都向下轉換(不確定這是否是正確的術語)為Item ,並且只會調用任何常用方法的基本 class 實現。

通過一個接口,列表中的每個 object 都保留了其特定類型的實現,因此我們可以在調用相同方法時從不同類型的對象中得到不同的結果。

這是一個例子,它可能不是最好的,但我認為它說明了這一點:

// 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...");
}

Output

請注意,在 output 中,我們為每個項目設置了不同的顏色,並且ItemWeapon之間的文本不同(即"selected""fired" ),並且每個項目都顯示它的唯一Name 此外,手槍使用FireColor (紅色)的基類實現,而RangedWeapon實現了它自己的顏色。

在此處輸入圖像描述

注意

@RufusL 回答了這個問題,我只是將其作為答案發布,而不是作為評論,以便更容易看到。

解決方案是簡單地使用is運算符。

我引用:

 if (item is RangedWeapon) { RangedWeapon rw = (RangedWeapon) item; // access RangedWeapon properties of rw here }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM