2011-12-15 47 views
2

我從來沒有對重載運算符做過任何廣泛的工作,特別是隱式和顯式轉換。帶數值類型和意外結果的顯式和隱式運算符

但是,我有幾個經常使用的數字參數,所以我創建一個結構作爲數字類型的包裝來強制輸入這些參數。下面是一個示例實現:

public struct Parameter 
{ 
    private Byte _value; 
    public Byte Value { get { return _value; } } 

    public Parameter(Byte value) 
    { 
     _value = value; 
    } 

    // other methods (GetHashCode, Equals, ToString, etc) 

    public static implicit operator Byte(Parameter value) 
    { 
     return value._value; 
    } 
    public static implicit operator Parameter(Byte value) 
    { 
     return new Parameter(value); 
    } 

    public static explicit operator Int16(Parameter value) 
    { 
     return value._value; 
    } 
    public static explicit operator Parameter(Int16 value) 
    { 
     return new Parameter((Byte)value); 
    } 
} 

,因爲我是用我的測試執行得到明確的和隱含的運營商的懸掛實驗,我想明確地蒙上了Int64Parameter類型和我的驚訝它沒有扔一個例外,甚至更令人驚訝的是,它只是截斷了數字並繼續前進。我試圖排除自定義顯式運算符,它仍然表現相同。

public void TestCast() 
{ 
    try 
    { 
     var i = 12000000146; 
     var p = (Parameter)i; 
     var d = (Double)p; 

     Console.WriteLine(i); //Writes 12000000146 
     Console.WriteLine(p); //Writes 146 
     Console.WriteLine(d); //Writes 146 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.Message); //Code not reached 
    } 
} 

所以我重複我的實驗與普通Byte代替我的結構,並具有完全相同的行爲,所以顯然這是預期的行爲,但我認爲有明確的轉換是導致數據丟失的將拋出一個例外。

+0

沒有,顯式轉換可能會丟失信息。隱式轉換不應該。 – 2011-12-15 21:08:52

+0

你是用`AnyCPU`,`x32`還是`x64`編譯? – ja72 2011-12-15 22:08:47

+0

@ ja72對不起,我的回覆延遲了,但是我正在使用x86 – psubsee2003 2011-12-16 10:07:24

回答

7

當編譯器正在分析的顯式用戶定義轉換它允許把一個顯式內置轉換的轉換的「任一側」(或兩者)。因此,舉例來說,如果你有從int弗雷德一個用戶定義的轉換,你必須:

int? x = whatever; 
Fred f = (Fred)x; 

那麼編譯器的理由「有從int弗雷德顯式轉換,這樣我就可以做出明確將int轉換爲int,然後將int轉換爲Fred

在您的示例中,存在從long到short的內置顯式轉換,並且存在從short到Parameter的用戶定義的顯式轉換,所以長轉換爲參數是合法的

隱式轉換的情況也是如此;編譯器可以在e上插入內置的隱式轉換在用戶定義的隱式轉換的另一端。

編譯器從不鏈接兩個用戶定義的轉換。

在C#中正確構建您自己的顯式轉換是一項艱鉅的任務,我鼓勵您停止嘗試這樣做,直到您對包含轉換的整個規範章節有徹底而深入的瞭解。

爲鏈轉換的一些有趣的方面,看到關於這個問題我的文章:

http://blogs.msdn.com/b/ericlippert/archive/2007/04/16/chained-user-defined-explicit-conversions-in-c.aspx

http://blogs.msdn.com/b/ericlippert/archive/2007/04/18/chained-user-defined-explicit-conversions-in-c-part-two.aspx

3

這個目標:

所以我創建一個結構圍繞數字類型的包裝,以強烈的類型,這些參數

而這種代碼:

public static implicit operator Byte(Parameter value) 
{ 
    return value._value; 
} 
public static implicit operator Parameter(Byte value) 
{ 
    return new Parameter(value); 
} 

是在總的矛盾。通過添加雙向隱式運算符,您可以取消包裝器可能帶來的任何類型安全。

因此請刪除隱式轉換。您可以將它們更改爲明確的。