2011-04-12 85 views
2

我有一個(很容易)的問題,似乎我無法找到如何做到這一點。我希望得到一些幫助。是否有抽象方法的顯式接口聲明?

我有兩個班,其是這樣的:

public class FileParameters { ... } 

public abstract class File { 
    ... 
    public abstract FileParameters Params { get; } 
} 

來自兩類我有一個派生特殊版本:

public class SpecialFileParameters { ... } 

public abstract class SpecialFile { 
    ... 
    private SpecialFileParameters params; 
    public override FileParameters Params { get { return params; } } 
} 

當我想用我不得不將目光投向SpecialFileParameters首先,例如:

((SpecialFileParameters)SpecialFileObject.Parameters).DoSomething(); 

這是相當討厭的。我想有基本相同的語法與接口

public abstract class SpecialFile { 
    ... 
    private SpecialFileParameters params; 
    private override FileParameters File.Params { get { return params; } } 
    public new SpecialFileParameters Params { get { return params; } } 
} 

但是這樣我得到一個編譯器錯誤:「文件」在顯式接口聲明不是一個接口。有沒有其他方法可以做到這一點?

一些進一步的信息:

  • 我不能改變的基類,只有我的特別班
  • 我真的需要2個特別的派生類,一種是用C#編寫,另外在C++/CLI。如果讓它工作的「技巧」在C#和C++ CLI之間是不同的,請讓我知道。

感謝您的幫助(和耐心,我想^^),

回答

1

沒有,有在C#中沒有語法(從另一種方法截然不同具有相同簽名)標誌着一個明確的抽象的覆蓋方法,以及因爲你不能在同一級別聲明兩個匹配的簽名,所以你不能完成你想要的。

既然你已經排除了改變的基類,我唯一​​的建議是增加一個額外的人工水平:

public abstract class File { 
    public abstract FileParameters Params { get; } 
} 
public abstract class FileIntermediate : File 
{ 
    public override FileParameters Params {get { return ParamsImpl; }} 
    protected abstract FileParameters ParamsImpl { get; } 
} 
public class SpecialFile : FileIntermediate 
{ 
    public new SpecialFileParameters Params { get { return null; } }// TODO 
    protected override FileParameters ParamsImpl {get { return Params; }} 
} 
+0

@Ben - 現在好多了? – 2011-04-13 05:11:07

+0

是的。許多。絕對。 – 2011-04-13 05:12:22

0

可以使用泛型來解決這個問題:

public class FileParameters { } 

    public class SpecialFileParameters : FileParameters{} 

    public abstract class File<T> 
     where T : FileParameters 
    { 
     private T _params; 

     public T Params { get { return _params;}  } 
    } 

    public class SpecialFileParams : FileParameters<SpecialFileParameters> { } 

當你訪問Params時你會得到具體的「Special」。

+0

OP無法更改基類,但... – bitxwise 2011-04-12 10:39:27

+0

@bitxwise我錯過了那個部分.. 在這種情況下,沒有辦法避免演員。 您可以使用不同名稱的單獨獲取器來獲取類型安全版本,但是如果您僅限於在抽象基礎中定義的獲取者,那麼這就是您必須遵守的合同... – NightDweller 2011-04-12 11:13:58

0

是否有必要在兩個方法(覆蓋和新方法)之間有相同的方法名稱?在這種情況下,我通常會創建一個返回多個派生類型的新名稱的新方法,然後有越權調用此方法在其實施:

public override FileParameters Params { get { return SpecialParams; } }  
public SpecialFileParameters SpecialParams { get { return params; } } 

這樣,當你有一個SpecialFile對象,你不需要演員。如果這不起作用,也許你可以更多地解釋爲什麼你需要方法的名稱與你的情況相同。

2

,它在C有些不同++/CLI,例如明確壓倒一切的:

public ref struct BaseClass abstract 
{ 
    virtual int Func(int) abstract; 
}; 

public ref struct DerivedClass : BaseClass 
{ 
    virtual int BaseFunc(int x) = BaseClass::Func { return x + 2; } 
    virtual int Func(int y) new { return y/2; } 
}; 

int main(array<System::String ^> ^args) 
{ 
    DerivedClass^ d = gcnew DerivedClass(); 
    BaseClass^ b = d; 
    System::Console::WriteLine("4 -> Base -> " + b->Func(4)); 
    System::Console::WriteLine("4 -> Derived -> " + d->Func(4)); 

    return 0; 
} 

馬克已經顯示出您所需要的C#做:使用繼承的附加層。

+0

顯式重寫與真正不相關我認爲這個問題(即,問題是錯誤的)。我認爲OP *真正需要的是covariant返回類型,這在C++/CLI(參見C2392)中不受支持,據我所知C#中不支持抽象類(而不是接口)。 – ildjarn 2011-04-13 06:10:05

+0

@ildjarn:顯式重寫是缺乏協變性返回的不完美解決方法。此外,該錯誤消息的描述不準確。錯誤消息本身是正確的:在託管類型中不允許協變返回。但是描述表明,在使用'/ clr'進行編譯時不允許這樣做,而實際的行爲是不管是否設置了/ clr,本機類型都允許協變返回。 – 2011-04-13 12:47:39

+0

道歉 - 累了,誤讀了代碼試圖做的事情。編輯所以我可以刪除downvote。 – ildjarn 2011-04-13 20:52:00