2016-06-25 42 views
3

考慮以下問題獲得對實例的引用,其構造已經拋出的異常

當設計一個框架,一個接口暴露一些事件呈現

interface I 
{ 
    event MyEventHandler MyEvent 
} 

此接口將最終被很多人實現不同的第三方供應商,並可能被不同的客戶使用。

由於每個供應商可能新向上事件參數無效的數據,我有作爲框架作者爲事件參數水平的唯一控制,所以我想以下圖案:

class MyEventArgs 
{ 

public int? MyProperty{get;} 

MyEventArgs(int arg) 
{ 

    if(arg.IsInvalidArgument())//Let's pretend that there's such an extension method 
    throw new ArgumentException(...) 

    MyProperty = arg; 
} 

這確保客戶端不能使用某些無賴代碼提供的無效值,因爲構造函數會拋出一個異常,因此整數將沒有賦值,使其成爲空引用。

然而,這也創造了客戶端代碼的開銷,因爲現在的客戶必須檢查的HasValue然後訪問,使得EventArgument不太人性化。這變得更加繁瑣時的參數量每事件爭論增長。

我可以在技術上去除的問號,這將擺脫可空廢話的客戶,因爲在我看來,有上帝的綠色地球沒有辦法獲得這樣的實例的引用,但問題是,這種情況雖然容易測試,但可能有我從未想到的邊緣情況,因此我的問題。

是否有任何可能的方式來獲取對其構造函數已引發異常並將其傳遞給事件偵聽器的實例的引用?

+0

我真的不清楚你想問什麼。首先,你在說什麼「開銷」?其次,你想要得到什麼「參考」? – CodeCaster

+0

@CodeCaster我編輯了我的問題。感謝您將注意力引入我的注意力..開銷是在事件參數類中爲每個屬性使用Nullable API,引用是構造函數引發異常的引用。 –

回答

3

當構造函數拋出異常沒有辦法以獲得該對象的引用(除非對象由前投擲端出this相配合;不太可能,設計不好)。

因此,您的無效值對象無法訪問。它的狀態確實無效(默認初始化),但沒有人能看到它。這就像一個內部損壞的虛擬機,並試圖發射導彈,但你已經禁用了虛擬網卡。

這種模式被用在各地。你已經使用過很多次而沒有意識到。例如,如果你說new FileStream(null)你將如何獲得對該無效流的引用?你不能。

只是做正常的事情。不過,你認爲這很好。

是否有任何可能的方式來獲得對其構造函數已引發異常並將其傳遞給事件偵聽器的實例的引用?

號,但這裏的地方有可能一個例子:

class C { 
public static C Instance; 
public C() { 
    Instance = this; //publish/leak 
    throw ...; 
} 
} 

只是不這樣做。無論如何,這是非自然的代碼。對象的構造函數通常不應該做太多的事情,它應該使對象進入有效狀態並且不會引起副作用。副作用是發佈對this的引用的唯一方式。

還有一個問題:如果存在一個終結器,將在該對象上調用終結器。終結器很少見,因爲大部分時間非託管資源都應該由句柄類來保存。出於這個原因,這個問題很少會生效。但是終結器可以看到它的對象的私有狀態。確保它可以解決這個問題。 FileStream s終結器可能會檢查中止的初始化並且什麼也不做。

0

回答你的問題。如果號在構造函數中遇到錯誤時,你不能有一個空的結果

但是我認爲解決這個問題的最好的方式是靜態的建構功能添加到MyEventArgs類

public static int DEFAULT_ARG = 1;//you can set this to whatever you want 
public static Create(int arg) 
{ 
    if(checkArg(arg)) 
    { 
     return new MyEventArgs(arg); 
    } 
    return new MyEventArgs(MyEventArgs.DEFAULT_ARG); 
} 

然後而不是使用var event = new MyEventArgs(arg);使用構造目錄使用var event = MyEventArgs.Create(arg);

這是一個有點使用多個EventArgs的這種方法的壓力,但嘿:)你總是可以推導出所有的人都來自同一個通用的抽象類

希望這有助於:)

+0

感謝您的更正,但是我不明白這對我有何幫助?我試圖建立的是,是否可以獲取實例,使無效的事件參數實例可以冒泡到客戶端代碼,儘管安全機制。 –

+0

是的解決方案將返回新的MyEventArgs(MyEventArgs.DEFAULT_ARG)而不是null –

+0

這確實是一個解決方案,但我想避免它,因爲這需要每個事件參數都有這樣的功能。另外,我的問題不需要解決方案,而是以「是/否」和「爲什麼」的形式提供更多答案。我非常感謝你的努力。 –

0

的客戶必須檢查HasValue,然後訪問Value

那麼它不是必要使財產Nullable<int>,因爲你只能從構造設置(假設省略了private set),它是不可空的。

是否有任何可能的方式來獲得一個實例,其構造已經拋出的異常

不,當一個構造函數拋出異常,你沒有得到一個實例回來的參考。

+0

這是必要的,以便屬性不會使用默認值進行初始化,例如可能在屬性域中有效的零。這就是爲什麼我把它放在第一位的原因。至於「你沒有得到一個實例回來」部分..你有什麼具體的支持這一點?我傾向於相信這一點,但我還沒有找到具體的答案。 –

+0

http://ideone.com/lDi9f7 – CompuChip

+1

@Eyal http://stackoverflow.com/questions/10119896/why-throwing-exception-in-constructor-results-in-a-null-reference。我目前無法對可空設計做任何說明。 – CodeCaster

相關問題