2012-06-13 92 views
13

所以,這實際上是這個問題是我目前的重點。 我正致力於重構我的個人項目,嘗試提高性能,優化內存使用,使代碼簡單明瞭。我有不同的應用程序層(實際上,DAL,BLL,ServiceAgent是WCF服務)。我使用實體/模型/ DTO在這些層之間傳遞數據,這是無狀態的(根本沒有任何邏輯)。目前這是一個這樣的對象DTO類與結構

public class Person 
{ 
    public ComplexId Id { get; set; } 
    public string Name { get; set; } 
    // ... 
} 

我以前使用這種方法,它就像一個「最佳實踐」,是嗎?這是存儲傳輸數據的最佳方式嗎?如果我改變它結構這樣的:

public struct Peson 
{ 
    public ComplexIdentifier ComplexId; 
    public string Name; 
} 
public struct ComplexIdentifier 
{ 
    public int LocalId; 
    public int GlobalId; 
} 

這將是更好的性能,從/內存使用的角度呢?或者也許有這樣的陷阱?

+2

「class」(這是一個簡單的; p) –

+0

感謝所有參與! –

回答

14

對於標準的DTO實體,您需要堅持使用該類。

A struct有更多有限潛在用例的範圍比類。當struct類型變得太大時(也不要忘記,它們是值類型,並在被複制時複製)也有效率問題,如MSDN guidelines about value types中所述。且不說陷阱的大量當你開始有struct類型通過屬性暴露,或不小心參考接口箱時,或使它們可變...

我不saying not to usestruct當它是相關的,但我很少發現自己需要在我們的主要桌面應用程序中使用struct類型 - 它是分層的並且具有DTO類型。


性能問題不能像 structclass一樣簡單地回答。您需要使用分析工具,例如 dotTraceANTS以便找到熱點並從那裏開始。性能問題不是微不足道的,好的工具通常是答案的開始。

+1

+1。一個附加:[可變結構是EVIL !!](http://stackoverflow.com/questions/441309/why-are-mutable-structs-vil) – Steven

+0

@Steven當然,我已經在我的答案中添加了該鏈接 - 有點潛意識;-) –

+0

同意。爲了緩解將值複製到這些對象以及從這些對象複製值的問題,請使用[AutoMapper](automapper.org)。 – bluevector

4

這是從性能/內存使用的角度來看更好的方法嗎?

編號結構是值類型,所以它們按值複製。這意味着,不是隻複製一個引用,而是始終複製完整的對象。如果有的話,它可能會稍微慢一些,並使用更多的內存(因爲對象將重複)。

爲什麼你不應該這樣做的另一個原因:應該總是避免可變結構,因爲如果你不小心,它們會引起意想不到的行爲。

2

A struct可能更危險的是CLR對值類型的處理要差得多,如果寫得不好(例如可變結構)會產生可怕的頭痛。 此外,如果您的類型包含許多字段,然後從方法傳遞到方法,則您將在每個方法調用上覆制每個字段的值,從而比首先使用類時使用更多的內存。

使用DTO(數據傳輸對象),這將鼓勵狀態和行爲的分離。如果正確完成,這可能是一個好設計(並且在大多數情況下,您可以使用類而不是結構來實現此模式)。

此外,使用struct作爲DTO object的具體情況似乎有缺陷,因爲它引入了不必要的redundancy。由於structs cannot inherit other structs,你不能表達是一種關係。當你有從Person繼承的Customer時,你會做什麼。你重複所有的Person properties in the Customer結構嗎?你是否在Customer結構中嵌套了一個Person結構?這兩種方法都不理想。如果您至少使用過類別,那麼您可以讓客戶擴展人員

1

您應該使用類方法,struct方法甚至可能會比較慢,因爲結構是值類型,無論您將它們作爲函數參數傳遞,都將進行復制。因此,您的DTO堅持課堂講話。

0

我的意見是:班級比較好。

使用類可以實現INotifyPropertyChanged接口如果您執行數據綁定,那將會非常有幫助。

你也可以有一些私人領域,比如只有「get」屬性的「ID」, 你可以給你的類添加一些方法,你可以讓你的實體可序列化。
我想說的是,你對類更加靈活,並且我不認爲在這種情況下結構和類之間有很大的性能差異。

這裏是一個非常不錯的書,對我幫助很大,通過設計n層的應用程序: http://msdn.microsoft.com/en-us/library/ee817644.aspx

看看那裏。它說: 「在結構和類之間進行選擇對於不包含分層數據或集合的簡單業務實體,請考慮定義一個結構來表示業務實體 對於複雜的業務實體或 需要繼承的業務實體,相反,將實體定義爲類。「

+0

我使用無狀態類 - 我知道INotifyPropertyChanged,但根據我的任務,我不需要它。我也不需要爲這些對象添加任何邏輯(方法)。只能獲取屬性 - struct可以有隻讀字段,可以'它嗎? –

+0

是的,你是對的。對不起,不好的例子。 – sickUnit

5

數據傳輸對象的兩個最佳選擇通常應該是一個深不可變的類對象,或者是一個具有適合用作數據傳輸對象的類型的暴露結構的結構。其他類型的結構有時也可以使用,但暴露域結構是迄今爲止最簡單的,簡單性是一個很大的優點。

的概念,可變的結構是邪惡的歷史可以追溯到一些早期的C#編譯器,其在

 
    SomeReadonlyStruct.SomeProperty = 5; 

會被編譯器默默轉換成:

 
    var temp = SomeReadonlyStruct; 
    temp.SomeProperty = 5; 

只讀屬性背後隱藏結構域是爲了確保前面的陳述會拒絕編譯而不是產生破損的代碼。由於較新的編譯器將拒絕改變只讀結構的可寫字段,所以不再需要將字段換成只讀屬性。

與其他類型的數據傳輸對象相比,帶有外露字段的結構具有巨大的優勢:每個結構具有適合於數據傳輸的類型的暴露字段,除了可能的構造函數外,沒有其他成員具有相同的行爲方式,沒有驚喜。有人從未使用結構可能會對他們不像類的行爲感到有點驚訝,但是理解這些結構作品如何理解它們是如何工作的人。

考慮下面的代碼:

 
    customerPhone = someDataSource.GetPhoneNumber(customerID); 
    customerPhone.Extention = "5309" 

有些人不喜歡的事實,如果customerPhone是一個裸露的場結構,設置Extension屬性將不會影響信息someDataSource。儘管編寫結構體字段不會更新其他任何東西,但如果customerPhone是可變類類型,情況會好得多。任何明白customerPhone是暴露字段結構類型的人都知道,對其成員的更改不會影響其他任何內容。相比之下,如果customerPhone是可變級類型,則上述代碼可能會通過更改與該customerID相關聯的電話號碼來更新someDataSource。或者它可能不會。或者,如果一個電話號碼與兩個customerID值相關聯,則上面的代碼可能會更改它們兩個。爲確定上述代碼可能產生的影響和副作用,可能需要研究的代碼量相當大。更糟的是,可能很難確定一個人沒有遺漏任何東西。

確實有一些地方傳遞類對象引用可能比傳遞結構更有效。也有少數情況下,可變類對象可以成爲類中有用的數據持有者。然而,一些通用的包裝器可以將一個結構包裝在一個可變或不可變的類中,並且在這些類型的類之間交換信息。

 
interface IReadableHolder<T> { T Value {get;} } 

class MutableHolder<T> : IReadableHolder<T> 
{ 
    public T Value; 
    IReadableHolder.Value {get {return Value;} } 
    public MutableHolder(T newValue) { Value = newValue; } 
    public MutableHolder(IReadableHolder<T> it) { Value = it.Value; } 
} 
class ImmutableHolder<T> : IReadableHolder<T> 
{ 
    T _Value; 
    public Value {get {return _Value;} } 
    public ImmutableHolder(T newValue) { _Value = newValue; } 
} 

如果沒有可變結構,這樣的構造會更笨拙。