2012-12-19 101 views
4

我有我的班上有幾個對話框,我試圖用一個函數初始化它們:無法施展派生類的基類

private void InitializeFileDialog(ref FileDialog fileDialog) 
    { 
     fileDialog.Filter = "Word Documents|*.doc|Excel Worksheets|*.xls|PowerPoint Presentations|*.ppt" + 
     "|Office Files|*.doc;*.xls;*.ppt" + 
     "|All Files|*.*"; 
     fileDialog.DefaultExt = "txt"; 
    } 

問題是,當我把它稱爲:

InitializeFileDialog(ref dialog); 

error CS1503: Argument 1: cannot convert from 'ref Microsoft.Win32.OpenFileDialog' to 'ref Microsoft.Win32.FileDialog'

我想投,但不能因爲某些原因。有什麼問題?是因爲FileDialog是抽象的嗎?我試圖查找,如果這是原因,但我找不到任何有用的東西。

下面是在Microsoft.Win32發現聲明:

public abstract class FileDialog : CommonDialog 
public sealed class OpenFileDialog : FileDialog 

我也試着使用泛型並沒有奏效。我錯過了什麼?

+3

刪除'ref'關鍵字。對象通過引用傳遞,所以在上面的例子中你不需要它。 – adrianbanks

+0

@adrianbanks它解決了問題!謝謝。但是爲什麼它會拋出一個錯誤? – MasterMastic

+0

@adrianbanks是正確的,但值得注意的是'ref'允許您爲傳遞的變量分配一個不同的對象,所以在某些情況下在傳遞對象時很有用。例如,將'null'分配給對象變量不會改變函數作用域之外的原始對象。有關更多信息,請參閱http://stackoverflow.com/questions/186891/why-use-ref-keyword-when-passing-an-object。 –

回答

4

最好的解決方案是刪除ref關鍵字。在這種情況下真的不需要。

您只有需要ref,如果您的方法應該能夠重新分配您傳入的變量,這應該幾乎不會。直接返回一個值或直接使用對象,通常就足夠了。

但是,編譯器錯誤來自於您需要傳入方法所需的確切類型的變量。就像這樣:

FileDialog baseDialog = fileDialog; 
// baseDialog might be a different object when this returns 
InitializeFileDialog(ref baseDialog); 

畢竟,作爲ref參數傳遞的原始變量可以用你的方法被重新分配。

現在如果將SaveFileDialog分配給您的原始變量OpenFileDialog會發生什麼?我們所知道的世界將會結束。這就是爲什麼你需要創建一個FileDialog類型的臨時變量。類型系統允許您的方法將任何派生類的對象分配給該變量。

見埃裏克利珀此博客條目更多信息這個有趣的話題:
Why do ref and out parameters not allow type variation?

總之:不要在這種情況下使用ref

+0

刪除'ref'工作,但我試圖找出爲什麼編譯器拋出一個錯誤。我甚至無法施展它(正如你先提到的那樣)。 – MasterMastic

+0

@Ken這是因爲當參數作爲'ref'傳遞時,該方法可以重新分配**原始**變量。當你只是施放另一個變量時,它不會創建一個新的變量,以便在重新分配新值之後存儲新值。 – Botz3000

+0

哦,現在我明白了!預計編譯器會更清楚。無論如何,非常感謝!我大部分時間花在C++上我只是無法得到這些類是沒有像這樣的運算符的引用。 – MasterMastic

0

問題出在ref關鍵字。它允許您替換呼叫者的參考。

例如:

static void Main(string[] args) 
{ 
    string str = "hello"; 

    SomeFunction(ref str); 

    Console.WriteLine(str); // outputs "world" 
} 

static void SomeFunction(ref string obj) 
{ 
    obj = "world"; 
} 

現在想象一下,你可以使用的基類,你有這種情況:

static void Main(string[] args) 
{ 
    OpenFileDialog dialog = new OpenFileDialog(); 

    SomeFunction(ref dialog); 
} 

static void SomeFunction(ref FileDialog obj) 
{ 
    obj = new SaveFileDialog(); 
} 

中的代碼SomeFunction是有效的,因爲SaveFileDialogFileDialog。但是,在Main函數中,您將分配一個SaveFileDialogOpenFileDialog,這是不可能的。這就是爲什麼在使用ref關鍵字時,您必須提供完全相同類型的參考。

要解決您的問題,只需刪除ref關鍵字。