是否有抽象方法的显式接口声明?

时间:2011-04-12 09:48:35

标签: c# .net c++-cli

我有一个(非常容易)的问题,似乎我无法找到如何做到这一点。我将不胜感激。

我有两个类是这样的:

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; } }
}

但是像这样我得到一个编译器错误:显式接口声明中的'File'不是接口。还有其他方法可以做到这一点吗?

进一步的信息:

  • 我无法更改基类,只能更改我的特殊类
  • 我实际上需要2个特殊的派生类,一个用C#编写,另一个用C ++ / CLI编写。如果C#和C ++ CLI之间的“技巧”不同,请告诉我。

感谢您的帮助(我的耐心,我猜^^),

4 个答案:

答案 0 :(得分: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;
}

Marc已经展示了你需要为C#做些什么:使用额外的继承层。

答案 1 :(得分: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; }}
}

答案 2 :(得分: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时,您将获得具体的“特殊”。

答案 3 :(得分:0)

是否需要在两个方法(覆盖和新方法)之间使用相同的方法名称?在这些情况下,我通常使用新名称创建一个新方法,该方法返回更多派生类型,然后让覆盖在其实现中调用此方法:

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

这样,当你有一个SpecialFile对象时,你不需要强制转换。如果这不起作用,也许你可以解释为什么你需要方法的名称对你的情况是相同的。