2011-10-15 73 views
16

我鄙視出來的和裁判的作爲方法參數。恕我直言,他們使代碼不那麼幹淨,並提供副作用的機會。但我承認我可能不瞭解他們的用處,這可能解釋我的一部分厭惡。請問,有人可以解釋一個有效的情況出來或參考?在方法中使用「out」或「ref」參數的正當理由是什麼?

+0

你在問這兩者之間的區別,或者一般使用它們的目的是什麼?爲什麼這個標記爲java? – Marlon

+2

你認爲他們如何提供機會對於副作用? – svick

+0

http://stackoverflow.com/questions/635915/when-to-use-ref-and-when-it-is-not-necessary-in-c-sharp –

回答

18

基本上,如果你需要返回多個值,它是使用類似Tuple<,>或自定義類型封裝值的替代品。規範示例可能是int.TryParse及相關方法。他們想要傳達兩個信息回:

  • 分析得到的值
  • 無論解析成功。

現在,這些可能實際上已經在這種情況下使用的int?等返回類型編寫的,但它是其他情況相同的原則。 (例如,Dictionary<,>.TryGetValue,其中存儲在字典中的值可以合法地爲空)。

我不會說我鄙視outref參數,但我相信他們應該只偶爾使用,並且只當沒有更好的選擇。我在堆棧溢出中看到的大多數ref的用法都是由於誤解了參數傳遞。

+0

'ref'用法的好例子是什麼? –

+0

@SaeedAmiri:大致相同,但您希望變量也可用作輸入。這有點像有一個「in」參數和另一個「out」參數,除了調用者不能分開這兩個參數:) –

+1

對不起一個問題,爲什麼.net團隊決定在tryparse中使用'out'而不是'ref'? –

6

out提供了一種方法返回多個值。 ref是相同的,但您可以傳中的值。

注意,您可以發生變異,即使沒有ref聲明的對象(假設它是在第一時間當然是可變的)。

我寧願out另一種方法是使一個類來包含所有返回值,並返回類的一個實例。

+0

不止一個,而不僅僅是兩個。 –

+1

「out」參數肯定會爲副作用提供機會 - 它們要求該方法要麼永遠運行,要麼異常終止,要麼變異變量*。這是一個副作用。 –

1

它們幾乎相同 - 唯一的區別是您作爲out參數傳遞的變量不需要初始化,並且使用參數out的方法必須將其設置爲某個值。

int x; 
Foo(out x); 

int y; 
Foo(ref y); 

Ref參數是可能被修改的數據,out參數是這對功能的額外輸出已經在使用的東西的返回值數據(例如int.TryParse)。

+1

這是真的嗎?參考文獻未初始化時會得到什麼錯誤? –

+0

另外OP要求在.net中使用它(通過知道可用的替代方法)而不是它們的區別, –

+2

@AshBurlaczenko:它當然是真的,如果你想知道你得到了什麼錯誤,請啓動編譯器並找出。 –

5

「新」(C#4.0)lock使用ref(技術上lock語句是新的Monitor.Enter過載的語法糖)。這是不可能做到這一點,而不:-)

bool acquiredLock = false; 

try 
{ 
    Monitor.Enter(lockObject, ref acquiredLock); 

    // Code that accesses resources that are protected by the lock. 

} 
finally 
{ 
    if (acquiredLock) 
    { 
     Monitor.Exit(lockObject); 
    } 
} 

所以在非常關鍵的地方ref空間。

爲什麼簡單地返回一個布爾值是不夠的原因是一個例外可以在Monitor.Enterreturn truebool acquiredLock =之間的一個問題:「離開你的程序鎖tacken發生?「ref參數解決了這個問題

+0

+1我正在尋找好的參考樣本 –

+0

但是,爲什麼不'var acquiredLock = Monitor.Enter(lockObject)'?儘管使用了'ref',我拒絕這是'*好需要*'。可以說標準的'Dictionary.TryGetValue'是一個更好的例子,因爲它有兩個必須返回的值(key found和value)。 – 2011-10-15 20:14:50

+0

@pst:再次閱讀最後一段。您不能*返回*鎖是否被採用,因爲當返回值被放到「堆棧」和返回值被複制到變量中時,*之間可能會有一個異常*。 –

相關問題