簡體   English   中英

從c#中繼承結構的夢想

[英]The dream to inherit from a struct in c#

在那里,我在C#XNA 4.0中制作2D游戲,並再次遇到我的小煩惱; 矩形 對於那些使用基本碰撞的人來說,這幾乎是必需的。 對於幾乎所有創建的游戲對象,您都需要有一個矩形。 然后我去改變X,檢查碰撞或其他任何東西。 在那里,我開始了objectName.Rectangle.Whatever的永無止境的戰斗。 為了解決這個問題,我當然會給出一些objectName屬性/方法來為我訪問這些屬性/方法。

然后我敢於夢想。 我有一個偉大的設計來制作一個基本的游戲對象類,所有drawable將繼承,這將允許父母,精確的本地坐標(浮點數),並保持紋理/ spritebatch。 為了完成這個,我准備從Rectangle繼承,使用它擁有的所有方法和屬性。 哎呀,每當需要一個Rectangle的東西時,我可能會懶得說objectName,而不是objectName.Rectangle。

然后我意識到,不是機會。 我開始感到沮喪,因為我很聰明的想法被砸碎了。 從那以后,我完美的小班級擁有一個矩形,各種方法和屬性根據需要訪問它。 我也有機會從XNA DrawableGameComponent繼承它。 雖然從長遠來看這更實用,每次我查看繪制或更新方法並看到我經常想到的矩形調用時,是否有希望做我想要的事情? 我可以做一些聰明的工作嗎? 或者是從一個真正被我掌握的矩形繼承而來?

雖然使用XNA中提供的DrawableGameComponent類允許大多數與游戲對象相關的動作發生在類Update()方法中,但每次在類之外我需要引用的不是Rectangle的屬性,而是Rectangle本身,我稍微考慮到實際上我的對象實際上是各種各樣的方式,並且加強了Rectangle。 然后我再一次發現自己在問:

有沒有辦法從預定義的結構繼承,或者給項目留下你的印象(一種解決方法)?

繼承否,但您可以使用擴展方法向Rectangle對象添加許多“默認”功能。 例如

  //(inside a static class)
  public static int GetSurface(this Rectangle rect){return rect.Width * rect.Height;}

  //calling
  Rectangle rect;
  var s = rect.GetSurface();

也就是說,我通常做的是封裝所述結構。 使用該類作為基礎對象,並添加一個運算符,以便可以將其隱式轉換為Rectangle。 這樣它就可以傳遞給一個需要一個矩形而不需要強制轉換的方法。

    public class MyRect //class so you can inherit from it, but you could make your own struct as well
    {
        public int X { get; set; }
        public int Y { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public int Right { get { return X + Width; } }
        public int Bottom{ get { return Y + Height; } }

        public static implicit operator Rectangle(MyRect rect)
        {
            return new Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
        }

        public static implicit operator MyRect(Rectangle rect)
        {
            return new MyRect { X = rect.X, Y = rect.Y, Width = rect.Width, Height = rect.Height };
        }

    }       
 }

現在,您可以手動或從現有的rect創建自己的rect:

  MyRect rect = ARectangleVar

並且您可以在遺留方法中使用它,這些方法期望不轉換矩形

這是一個可能的解決方法(把它放在MyClass ,你所說的具有Rectangle屬性的類):

public static implicit operator Rectangle(MyClass obj)
{
    return obj.Rectangle;
}

這將允許您將對象傳遞給期望Rectangle的方法,並且它可以工作。 請注意,與真正的繼承不同,存在的Rectangle與傳入的MyClass實例不同,它只是由值構成的結構。

值類型從根本上與適用於類類型的繼承風格不兼容,但是能夠以這樣的方式聲明“派生結構”將有助於編譯器識別派生之間的雙向身份保留轉換。類型和原始。 派生的結構將需要只有一個字段,稱為“Base”(盡管C#編譯器可以接受關鍵字base作為替代),其類型是派生的結構的類型。 名稱與周圍類型的名稱不匹配的“Base”的所有成員將被視為封閉結構的成員。

“派生結構”提供的主要內容,但目前缺乏的主要內容是:

  1. 能夠訪問包裝結構的成員而無需添加額外的語法間接層。 例如,如果有一個實例`MyFancyPoint`是從`Point`中剔除的類型,可以說`MyFancyPoint.X + = 5`而不是'MyFancyPoint.Base.X + = 5`。
  2. 能夠一次執行多個隱式或顯式類型轉換。 C#通常只允許從“X”轉換為“Y”,除非存在直接轉換,部分原因是搜索所有可能的轉換序列很困難,部分原因是這樣做通常會產生關於轉換序列的模糊性應該受雇。 如果假定包裝特定結構的所有類型都表示具有保留標識的突變的“雲”,則兩個派生結構“XX:X”和“YY:Y”之間的轉換可以被明確地視為轉換為“X”。 ,然后是“Y”,然后是“YY”(如果存在“X”到“Y”轉換,那將是合法的)。
  3. 能夠將ByRef作為ByRef的一種類型的實例視為另一種類型的實例,將ByRef視為一種字段的ByRef,將其視為另一種類型中相應字段的ByRef。

我不確定是否需要對運行時進行任何更改以支持任何這些功能,如果接受盒裝派生類型的項目只能將其取消裝箱為同一派生類型; 允許將框架版本的結構直接轉換為身份可轉換派生的實例,這將有所幫助,但可能會增加復雜性。 我不確定是否需要這樣的行為來使泛型工作。 不幸的是,我覺得許多負責做出這種決定的人真的不喜歡價值類型。 由於.net歷史早期的一些設計決策(特別是缺乏“const ref”參數和通過ref公開屬性的方法),使結構以語義正確的方式工作可能是一個挑戰,我想一些實現者寧願使用結構的問題作為改進.net處理它們的借口,而不是添加可以解決問題的功能。

暫無
暫無

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

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