簡體   English   中英

C# - 如何防止引用類成員?

[英]C# - How to prevent a reference being taken to a class member?

我有一個類(myClass),它包含一個私有類成員(類型為myData的currentData)。 我有一個屬性(CurrentData),允許“獲取”該成員。 我想允許用戶調用currentData上的函數,但是阻止他們對它進行外部引用。 例如。

myClass a = new myClass();

// This is OK
a.CurrentData.somefunc();

// This is what I dont want
myData m = new myData();
m = a.CurrentData;
// ... some time passes here...
m.someFunc();

雖然我理解他們引用相同的對象。 由於內部成員可能會意外更改,因此我不希望將我的課程之外的引用保留給內部成員。

這可能嗎? 我已經離開了c#這么久我不記得它是如何工作的!

沒有辦法

a.CurrentData.somefunc();

合法但是

m = a.CurrentData;

非法。 a.CurrentData.somefunc(); 本質上返回對a.CurrentData的內聯引用,然后在該引用上調用somefunc()

如果要阻止對內部對象的引用,則必須將方法添加到包含的類,然后將其傳遞給包含的對象:

public void DoSomeFuncWithCurrentData()
{
   this.currentData.someFunc();
}

myClass a = new myClass();

a.DoSomeFuncWithCurrentData();

沒有直接的方法來“禁止”引用。

但是,有一些可能的解決方法:

  • 創建代理方法 :根本不允許公共訪問CurrentData屬性。 為可在CurrentData上調用的每個方法創建代理方法:

     myClass a = new myClass(); a.SomeFuncOnCurrentData(); 

    這樣,您就不會將類的內部工作暴露給外部。 缺點是您必須編寫大量樣板代碼(或使用一些為您編寫樣板代碼的第三方工具)。

  • 返回副本 :使用GetCurrentData方法替換CurrentData屬性,並在每次調用時返回內部對象的新副本 這樣,用戶可以根據需要操作“舊”數據,並且用戶的對象與內部對象斷開連接。

  • 替換內部對象並使舊內容保持不變 :使MyData成為不可變類。 CurrentData更改時,不要修改MyData,而是創建一個新的MyData對象。 這與前一點(返回副本)具有相同的效果,但您可以繼續使用不需要在每次調用時創建副本的屬性。

  • 使舊內部對象無效 :當CurrentData更改時,請執行以下步驟:

    • 在內部使用MyData的新實例,
    • 在舊實例上設置一個標志,這會導致someFunc拋出ObjectExpiredException

您無法阻止用戶對對象進行外部引用,但您可以執行以下兩項操作之一來使此類引用無關緊要:

  • 使內部對象不可變 - 這樣外部引用就不可能改變對象內部的內容。 這就是.NET庫對字符串的作用。
  • 返回防御性副本 - 這樣就可以進行外部修改,但它們會發生在對象的副本上。

另一種可能性是使您的類成為結構,在這種情況下根本不可能創建引用。 這應該非常小心,因為使用值類型還有其他含義。

如果這樣可以:

a.CurrentData.somefunc();

但這不行:

var currentData = a.CurrentData;
currentData.someFunc();

然后在句法上(即靜態地)你不能禁止在將來的任意時間使用引用。 您可以做的最好的事情是將此要求構建到包含類myClass 如果你將方法someFunc()someFunc()作為myClass上的一個方法,那么只有當它們具有對myClass的引用時,你才會隱式地允許調用(內部)函數。

此外,如果這是一個很好的解決方案,您應該刪除CurrentData屬性,因為它正在發布一個私有表面區域。 傳播myClass需要從CurrentData公開的任何方法作為myClass方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM