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

本文关键字:接口 声明 抽象方法 是否 | 更新日期: 2023-09-27 17:49:58

我有一个(相当容易)的问题,似乎我不知道如何去做。我很感激你的帮助。

我有两个类是这样的:

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();

非常令人讨厌。我想要的语法与interface

基本相同
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之间是不同的,请告诉我。

谢谢你的帮助(我猜还有耐心^^),

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

在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#需要做的事情:使用一个额外的继承层

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

你可以使用泛型来解决这个问题:

    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"

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

public override FileParameters Params { get { return SpecialParams; } }     
public SpecialFileParameters SpecialParams { get { return params; } } 
这样,当你有一个SpecialFile对象时,你就不需要强制转换了。如果这不起作用,也许你可以解释一下为什么你需要在你的情况下使用相同的方法名。