2011-04-12 49 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