2016-12-27 69 views
2

我有小幫手類。這些類在內部用於確保某些類型的字符串始終具有適當的格式(郵件地址,電話號碼,ID,URL,鍵,顏色...)。IDisposable - 在沒有外部引用的情況下在類中處理什麼?

我希望把它們變成使用塊,要能夠回收的變量名:

using(Id id = ids.First()) 
{ 
    Container container = containers.getById(id); 
    ... 
} 
foreach(Id id in ids.Skip(1)) 
{ 
    Container container = containers.getById(id); 
    ... 
} 

當我這樣做時,Visual Studio問我這些類標記爲Disposable,我做到了,但我我不知道如何處理方法存根。讓我們來「郵件地址」類爲例:

public class MailAddress : IEquatable<MailAddress>, IDisposable 
{ 
    const string MAILADDRESSPATTERN = ... 
    protected string _address; 
    public MailAddress(string address) 
    { 
     if (address == null) throw new ArgumentNullException("address"); 
     if (!Regex.IsMatch(address, MAILADDRESSPATTERN)) throw new ArgumentException("address"); 
     this._address = address.ToLower(); 
    } 

    bool IEquatable<MailAddress>.Equals(MailAddress other) 
    ... 
    public override int GetHashCode() 
    ... 
    ... 
    ... 
    public override string ToString() 
    ... 

    public void Dispose() 
    { 
     throw new NotImplementedException(); 
    } 
} 

究竟會在Dispose功能有這樣一類呢?我必須處理哪些垃圾收集器會自動執行哪些操作?

到目前爲止,我沒有在任何地方給那個班級打電話Dispose,而且它似乎工作正常。現在,該班級是Disposable,我是否必須在整個代碼中添加對Dispose的呼叫?

+0

如果你的類沒有使用非託管資源,那麼'IDisposable'沒有用處。 –

+0

垃圾收集器僅處理受管資源。你只需要實現IDisposable你的類正在使用非託管資源,如COM對象。 using語句處理爲您處置的呼叫。 –

回答

3

您的Dispose方法毫無用處,因爲您似乎沒有任何非託管資源。 Dispose僅在您希望手動處理這些資源的情況下有用。

所有託管資源都由GC垃圾收集,因此不需要任何操作。刪除班上的IDisposable似乎是合適的操作。這將需要刪除的無用using過,你可以換取簡單的括號:

{ 
    Id id = ids.First(); 
    Container container = containers.getById(id); 
    ... 
} 
+0

更確切地說'Dispose'對託管對象也有意義:'Dispose'方法釋放耗費大量內存的管理對象,或者比垃圾回收器非確定性回收更快消耗稀缺資源。 (https://msdn.microsoft.com/en-us/library/fs2xkftw(v=vs.110).aspx) – Zharro

+0

好的,這也是一個很好的場景。 –

+0

@PatrickHofman要說「Dispose只在你想手動處理非託管資源的情況下有用」是不正確的和誤導性的。現在在非託管資源周圍實施封裝是相當罕見的。通常會使用IDisposable來控制受管資源的及時發佈。例如,MySocket.Dispose控制及時發佈託管的底層套接字,以便用戶可以控制端口關閉的時間(不是IF)。 – Ricibob

5

編譯器強制您在Id類中實現IDiposable接口,因爲您在using中使用它。 using的唯一目的是在您離開該區塊後致電IDisposable.Dispose。所以你只能在IDisposable的實現中使用它。

IDisposable的用途是在對象不再使用時清理外部資源。這包括關閉文件,從數據庫斷開連接,返回窗口句柄等等。

由於您似乎沒有進行清理,因此您不需要using聲明。在這種情況下,當你使用using(例如你正在使用不同類型的對象,其中一些具有外部資源的一種方法),你還是要落實Dispose方法來滿足接口,但你可以讓它空。

如果你的班級是一次性的,你確實應該在你不再需要時處置它,即使Dispose什麼都不做。如果您或其他人稍後將清理代碼添加到Dispose,則應該依靠它被執行。

6

不這樣做,你在濫用語言和Disposable接口/模式。

IDisposable是有非常特殊的原因,其中有非託管資源,或當你的類擁有一次性引用的確定性釋放。

這當然不是創建局部範圍的手段,因此您可以重用變量名稱。如果你需要做的是簡單地做:

{ 
    Id id = ids.First()) 
    Container container = containers.getById(id); 
    ... 
} 
+0

他爲什麼濫用這種語言? –

+0

@PatrickHofman使用'using'來創建本地範圍? – InBetween

+0

沒關係,明白你的意思。簡單的括號也可以完成這項工作。 –

1

不知道爲什麼你正在使用的using關鍵字。當執行離開using的範圍時,using關鍵字會對Dispose()進行調用。因此,using括號內的對象必須是IDisposable。如果您沒有任何資源需要清理,則無需將對象包裝在using中。由於在.net中使用析構函數並不是一個好主意,因此您將放入析構函數的邏輯通常放在Dispose()方法中。當與關鍵字using結合使用時,可以實現受控的資源管理。

相關問題