2015-08-18 68 views
2

在我目前的項目中,我需要大量的數據,特別是深入瞭解什麼是副本和什麼是參考 - 實施大量的深度克隆。謝天謝地,我的很多數據都包含在簡單的結構中,所以我可以將它們分配或傳遞給參數,並確保它們不相互引用。假設一個類型是一個結構是基於邏輯的一種不好的做法嗎?

但是,我意識到這樣做的代碼是基於這些類型是struct的假設,並且如果有人在某段時間將其類型更改爲類,他們可能不會注意到錯誤當他們這樣做的時候,這將是一個難以調試的地方。一般來說,我認爲代碼的正確性是基於在同一個文件中沒有明確說明是嗅覺的假設,尤其是當這個假設可以在不立即破壞構建的情況下被改變的情況下。所以,這種情況真的給我一個難聞的氣味。

我在做什麼真的是一個不好的做法?你是否遇到過我在真實代碼庫中描述過的任何問題,或者我是在想象什麼?如果你有,那麼將事情變得更加明確的好方法是什麼?


下面是我在說什麼(這是我的實際代碼,所有的名稱改變和其他功能剝離)的例子:

public class Example 
{ 
    public readonly DataOfType; 
    public readonly DataOfOtherType; 

    public Example(Type _DataOfType, OtherType _DataOfOtherType) 
    { 
     DataOfType = _DataOfType; 
     DataOfOtherType = _DataOfOtherType; 
    } 

    public Example DeepClone() 
    { 
     return new Example(DataOfType, DataOfOtherType); 
    } 
} 

DeepClone方法是正確的,因爲Type是枚舉和OtherType是一個結構,但你永遠不會知道它從這個代碼。

+1

您可以發佈一段代碼,說明您所描述的內容。謝謝 – Christos

+0

@Christos更新了問題 –

回答

3

您可以創建一個通用約束來僅允許結構但不可生成,然後在需要假設的每個方法的頂部創建該類型的變量。

例如爲:

public class AssumeStruct<TStruct> where TStruct : struct 
{ 
    private AssumeStruct(){} 
} 

然後:

public void MethodAssumingStructSemantics(S1 arg1) 
{ 
    AssumeStruct<S1> t = null; 
    ... 
} 

如果S1類型的性質是後來改這應該然後導致編譯器錯誤。

+0

這是非常棒的解決方案,謝謝! –

0

如果您使struct不可變,應該在我看來,一旦struct成爲類,您將不會遇到引用被散佈的問題。

除此之外,我認爲你必須幫助struct的'維護者'和'用戶'瞭解其含義。

您可以使用Visual Studio代碼文檔中的remarks部分輕鬆完成此操作。這會在每個引用該類型的人上彈出。

我不會對代碼做太多的修改來顯示數據類型是struct或者做一些類型檢查。這隻會導致混淆。

2

我認爲你應該從可變性的角度思考它,而不是根據參考和副本思考數據。

如果你有一個不可變的類型,那麼它是無關緊要的,如果它是一個結構或類,你可以把它相同,因爲你知道它不能改變。您可以安全地傳遞它,而不必關心它是引用還是副本,這只是一個實現細節。

無論何時您需要更改某個值,不變性都會強制您創建副本。這樣,你永遠不會在另一個地方使用某個地方的價值。

String類是一個如何使用它的例子。由於字符串是不可變的,你可以將它們作爲引用傳遞,而不會有字符串不斷變化的風險。 String類中對字符串進行更改的所有方法都會創建一個新字符串並顯示結果。

相關問題