2012-02-29 16 views
6

相關問題:Accessing a Class property without using dot operator鑄造我的同班同學的Int64,雙等

我已經創建了一個名爲MyDouble類看起來像這樣

class MyDouble 
{ 
    double value; 
    //overloaded operators and methods 
} 

我能夠做各種操作上MyDouble。例子:

MyDouble a = 5.0; 
a += 3.0; 
...etc 

然而,這仍然拋出一個錯誤

MyDouble a = 5.0; 
long b = (Int64)a; //error 
long b = (int64)a.value; //works 

我如何定義它,使得像(Int64)a操作自動轉換爲(Int64)a.value?我不希望用戶不必擔心value屬性的存在。

+0

爲什麼你同時使用'long'和'Int64'?一個是另一個的aloas,我認爲更習慣的方式是使用別名,如果它們存在而不是類型名稱。 – Joey 2012-02-29 07:10:40

回答

9

爲了使此轉換生效,您需要將explicit conversion添加到Int64。

這看起來像:

class MyDouble 
{ 
    double value; 

    public static explicit operator Int64(MyDouble value) 
    { 
     return (Int64)value.value; 
    } 
} 
+0

完美,謝謝。 – xbonez 2012-02-29 07:10:05

+0

爲什麼它必須是明確的?隱式轉換也適用,並且轉換變爲可選。 – Jay 2012-02-29 07:18:31

+0

@Jay您*可以*執行隱式操作,但OP顯示包括轉換操作符。就我個人而言,我傾向於嘗試避免隱式轉換,除非它們具有很大的意義(儘管隱含地從double轉換爲long似乎是個壞主意)。 – 2012-02-29 07:30:43

1

有從double到Int64的顯式轉換,但不能從你的類的Int64。所有你需要做的就是定義一個。或者,如果您的班級轉化爲雙倍班級,我認爲您可以這樣做:

long x =(long)(double)a;

但是,這很麻煩;我會定義顯式轉換運算符。

轉換應該是明確的,而不是隱含的,除非你有明確的理由。

語言定義的從雙倍到長的轉換是明確的,因爲轉換可能會導致信息丟失。由於有一些雙打,比如0.5,不能完全轉換爲長時間,因此您可能會因此轉換而丟失信息。這被稱爲縮小轉換

使用語言定義的轉換,縮小轉換是明確的。如果它們是隱式的,程序員可能會通過將一個類型的值賦給另一個類型的變量而意外丟失信息。將這種轉換定義爲隱含的違反了完全合理的原則,因此必須有一些令人信服的理由。

下面是一個例子,顯示了這個原理的價值。如果縮小轉換次數是隱含的,則會使代碼變得更脆弱。假設雙重轉換爲int轉換:

class Family 
{ 
    ICollection<Person> Children { get; set; } 
} 

int GetAverageNumberOfChildren(IEnumerable<Family> families) 
{ 
    return families.Sum(f => f.Children.Count)/families.Count(); 
} 

void SomeMethod(IEnumerable<Family> families) 
{ 
    int averageNumberOfChildren = GetAverageNumberOfChildren(families); 
    //... 
} 

糟糕!我們有一個錯誤! GetAverageNumberOfChildren應該返回一個雙!我們來修復它!

double GetAverageNumberOfChildren(IEnumerable<Family> families) 
{ 
    return families.Average(f => f.Children.Count); 
} 

哎呀,一切都編譯和運行!當然很高興我們發現了這個bug!

但是,可悲的是,沒有。 我們還有一個bug!SomeMethod隱式地將double轉換爲int,所以在期望值可能爲2.4的情況下,實際值爲2

由於double-to-int轉換爲顯式,編譯器將我們從我們身上拯救出來。在修復GetAverageNumberOfChildren,之後,錯誤的程序不能編譯。現在

,如果你的MyDouble類有一些驗證是限制它等於或大於long範圍小的範圍內的整數值,那麼你就可以安全地進行轉換隱。但在這種情況下,當然,您應該使用long,而不是double

1

隱式轉換可以像顯式轉換一樣工作。

public static implicit operator long(MyDouble m) 
{ 
    return (long) m.value; 
} 

有了這個地方,你可以這樣做:

long b = (Int64) a; 

或只是

long b = a; 

這僅僅是爲了說明轉換不一定是明確的。但如前所述,應該是,因爲有數據丟失的可能性。

+0

這是真的,但很危險。請參閱我編輯的答案以獲取解釋。 – phoog 2012-02-29 17:30:11

+0

@phoog我明白了。我只是對「你需要*顯式轉換」的語言提出質疑。 – Jay 2012-02-29 17:41:31

+0

夠公平的;我只是認爲,如果我們正在討論隱式轉換的存在,那麼明智地討論明確縮小轉換的原因。否則,有人可能會試圖實施一種轉換,因爲它更容易「或」因爲它使我的代碼更清潔「,所以應該明確地將其作爲隱式轉換,而不考慮編寫錯誤程序的可能性增加。 – phoog 2012-02-29 17:52:19