簡體   English   中英

為什么我不能將一個隱式運算符從Base類寫入C#中的Derived類?

[英]Why can't I write an implicit operator from a Base class to a Derived class in C#?

public class Derived : BaseClass
{
    public Derived(string name) : base(name) {}

    public static implicit operator BaseClass(Derived derived)
    {
        return new BaseClass(derived.ColorHex);
    }

    public static implicit operator Derived(BaseClass baseclass)
    {
        return new Derived(baseclass.name);
    }
}

這不行。 為什么不允許?
可以寫出有必要的邏輯,特別是在從基礎轉換為派生的邏輯時。

編輯:更改了問題的標題

因為已經有從DerivedBaseClass的隱式轉換,並且反過來沒有任何意義。

關於后者:如果您的Base對象可以隱式轉換為Derived - 為什么它們不是Derived對象?

標准的強制性引用:

6.1.6隱式引用轉換

隱式引用轉換是:

  • [...]
  • 從任何類型S到任何類型類型T,只要S來自T.

這表示存在一個隱式轉換Derived => Base ,我們都知道。

6.2.4顯式引用轉換

顯式引用轉換是:

  • [...]
  • 從任何類型S到任何類型類型T,只要S是T的基類。
  • [...]

這表示已經有一個顯式轉換Base => Derived (這是允許你在運行時嘗試向下轉換的原因)。

6.4.1允許的用戶定義轉換

C#僅允許聲明某些用戶定義的轉換。 特別是,無法重新定義已存在的隱式或顯式轉換。

這說明由於兩種興趣轉換已經由語言定義,因此您無法重新定義它們。

因為它會擾亂多態性的系統。

通常的規則是將對象轉換為自己的類型的結果是原始對象。 如果BaseType類型的存儲位置包含DerivedType的實例, DerivedType原始類型轉換為DerivedType應該告訴編譯器使用DerivedType的成員,但實際上不應該對該對象“執行”任何操作。 如果允許自定義的從基礎到派生的轉換運算符,則有必要:(1)具有轉換為實例的自有類型操作有時會產生新對象,有時不產生,或者(2)具有派生類型存儲在基本類型存儲位置中的對象與基本類型或不相關類型的對象的行為基本不同,沒有明確可見的類型檢查代碼,這將使其這樣做。 雖然有時候人們可能想要一個方法,給定一個base-type參數,可能會返回一個新的派生類型對象,或者 - 如果給定一個派生類型的實例,只需返回它未經修改,通常更好的方法是有這樣的東西“看起來”像一個方法而不是類型轉換。

順便說一句,有一種情況是編譯器可以在“基本類型”和“派生類型”之間允許用戶定義的類型轉換而沒有上述歧義:當其中一個類型是結構時。 雖然C#假裝值類型繼承自ValueType ,但每個值類型定義實際上定義了兩件事:一個派生自ValueType的堆對象類型,以及一個存儲位置集合,它不是一個對象,也不是從任何東西派生的。 C#定義了從后一種類型到前者的隱式轉換運算符,以及從前者到后者的顯式轉換運算符。 由於堆對象和存儲位置集合之間的轉換永遠不會引用保留,因此允許在此類上下文中使用用戶定義的轉換運算符不會導致混亂的繼承語義。 這種轉換的唯一困難是使用它們的值類型要么作為泛型類型不可用,要么如果作為泛型類型傳遞則會丟失它們的特殊行為。

要合成,您可以將Derived對象轉換為BaseClass對象,而無需編寫任何代碼:

BaseClass baseClass = new BaseClass("");
Derived derived = new Derived("");

baseClass = (BaseClass)derived;

但是你無法將Derived重寫為BaseClass。

對於其他演員,從BaseClass到Derived,它沒那么有意義。

總之,只有在兩個類之間沒有繼承關系時,才能重新定義強制轉換。

我需要能夠從基礎對象創建派生對象,以捕獲基類沒有的其他信息。 出於我的目的,構造一個派生對象,其中包含從基礎對象復制的所有字段。 我使用AutoMapper讓我的生活更輕松:

class AnnotatedAlert : Alert
{
    public string Color;

    // I don't know why C# doesn't allow user defined conversions from a base class
    // so I am creating a conversion constructor instead
    public AnnotatedAlert(Alert from)
    {
        AutoMapper.Mapper.Map(from, this);
    }

    static AnnotatedAlert()
    {
        AutoMapper.Mapper.CreateMap<Alert, AnnotatedAlert>();
    }
};

暫無
暫無

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

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