簡體   English   中英

使用隱式/顯式轉換而不是構造函數的原因是什么?

[英]What's the reason of using implicit/explicit convertions instead of constructors?

一個例子是:

XNamespace ns = "my namespace"

為什么不?:

XNamespace ns = new XNamespace ( "my namespace" )

使用隱式/顯式轉換而不是構造函數的背后的想法是什么? 方便?

是否有指導方針?

方便?

或多或少,是的。 考慮當您有一個類似數字的對象(例如Complex )進行計算時的情況。 顯然,編寫如下代碼:

Complex result = c1 * new Complex(2) + new Complex(32);

非常煩人且難以閱讀。 隱式轉換在這里有幫助(在此示例中,一種替代方法是運算符重載,但這會導致很多類似的重載)。

是否有指導方針?

提供盡可能少的隱式轉換,因為它們可能隱藏問題。 隱式轉換將顯式性降低的程度與其增加簡潔性的程度相同。 有時候這很好,但有時卻不好。

我發現最好將隱式轉換限制為非常相似的類型,例如上面示例中的數字類對象: int本質上是Complex (從數學的角度;即使不是通過繼承建模),因此是隱式的轉換很有意義。

在VB中,隱式轉換稱為“ Widening ”(與Narrowingexplicit )相反),這很好explicit描述了這一點:在轉換過程中不會丟失任何信息。

此外,運算符本質上是一個構建器函數,並且具有(某些)構建器函數相對於構造器的通常優點:即,它可以重新使用緩存的值,而不必始終創建新實例。

考慮我的Complex示例。 我們可能要緩存常用復數的值:

Class Complex {
    // Rest of implementation.

    private static Complex[] cache = new[] {
        new Complex(-1), new Complex(0), new Complex(1) };

    public implicit operator Complex(int value) {
        if (value >= -1 && value <= 1)
            return cache[value];
        else
            return new Complex(value);
    }
}

當然,這種微觀優化是否有效是另一個問題。

我認為,將隱式轉換與XName這樣的簡單類型一起使用的原因之一是調用方法的方便。

例如,你可以寫

var info = root.Elements ("user").Element ("info").Value;

LINQ的目的是簡化數據提取,如果我們不得不寫的話

var info = root.Elements (new XName ("user")).Element (new XName ("info")).Value;

即使是最簡單的查詢,LINQ對於復雜的查詢也完全值得嗎?

這里的另一個重要問題是XName被原子化。 參見MSDN

保證XName對象被原子化; 也就是說, 如果兩個XName對象具有完全相同的名稱空間和完全相同的本地名稱,則它們將共享相同的instance 為此,還明確提供了相等和比較運算符。

除其他好處外,此功能還可以更快地執行查詢。 在過濾元素或屬性的名稱時,謂詞中表示的比較使用身份比較,而不是值比較。 與比較兩個字符串相比,確定兩個引用實際引用同一對象要快得多。

您不能在構造函數中提供原子化,但是定義轉換后,您可以從池中選擇相應的對象,並將其作為新實例返回。

隱式/顯式轉換的使用是方便的問題,許多編程准則都建議您避免使用顯式ConvertToXXX方法。

問題之一是使用隱式/顯式轉換會進一步重載強制轉換運算符的功能。 它具有雙重目的

  • 通過對象層次結構中的不同類型/接口查看同一對象
  • 將對象完全覆蓋為新類型

不幸的是,C#已經在其他領域(使用基元和裝箱)完成了后者。

如果兩個類可以相互轉換,但它們不共享自動允許此行為的基類的接口,則可以使用轉換。 隱式轉換永遠不會丟失數據; 它們通常被視為“擴大”轉化。 例如,將int轉換為long就是擴大的轉換,並且隱式轉換沒有內在的問題。 顯式轉換可能會導致數據丟失; long可能會轉換為int ,也可能無法轉換為int ,具體取決於其值。

我用於隱式轉換的一個技巧是,當我沒有其他合理的選擇時,將不同名稱空間中的類彼此轉換。 例如,一個WCF服務返回一個AuthenticationToken對象,我需要將該對象傳遞給另一個命名空間中的WCF服務。 兩者都具有這個AuthenticationToken對象,並且進行常量轉換將是一件痛苦的事情。 我的解決方案涉及在部分類中使用public static implicit operator來添加功能以每種方式進行轉換。

就個人而言,當我知道rhs可能會轉換為類的靜態成員時,我會使用這些轉換(例如說color = "red"表示color = Colors.Red

我打算實際創建新實例時使用new運算符。

暫無
暫無

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

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