C# 抽象方法是否有明确的接口声明?

C# 抽象方法是否有明确的接口声明?,c#,.net,c++-cli,C#,.net,C++ Cli,我有一个(相当简单的)问题,似乎我不知道怎么做。我希望能得到一些帮助 我有两门课是这样的: public class FileParameters { ... } public abstract class File { ... public abstract FileParameters Params { get; } } 从这两个类中,我都有一个派生的特殊版本: public class SpecialFileParameters { ... } public abst

我有一个(相当简单的)问题,似乎我不知道怎么做。我希望能得到一些帮助

我有两门课是这样的:

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”不是接口。还有别的办法吗

一些进一步资料:

  • 我不能更改基类,只能更改我的特殊类
  • 我实际上需要两个特殊的派生类,一个是用C#编写的,另一个是用C++/CLI编写的。如果使“工作”的技巧在C和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> { }
公共类文件参数{}
公共类SpecialFileParameters:FileParameters{}
公共抽象类文件
其中T:FileParameters
{
私人T_参数;
公共T参数{get{return_Params;}}
}
公共类SpecialFileParams:FileParameters{}

当您访问参数时,您将得到具体的“特殊”值。

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

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

这样,当您有一个特殊文件对象时,您就不需要强制转换。如果这不起作用,也许您可以进一步解释为什么需要方法的名称与您的情况相同。

在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;
}
public ref struct基类摘要
{
虚int函数(int)抽象;
};
公共引用结构DerivedClass:基类
{
虚int BaseFunc(int x)=基类::Func{return x+2;}
虚int Func(int y)new{返回y/2;}
};
int main(数组^args)
{
DerivedClass ^d=gcnew DerivedClass();
基类^b=d;
系统::控制台::写线(“4->Base->”+b->Func(4));
系统::控制台::写线(“4->派生->”+d->Func(4));
返回0;
}

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

@bitxwise我错过了这一部分。。在这种情况下,没有办法避免演员阵容。您可以使用具有不同名称的单独getter来获得类型安全版本,但如果您仅限于抽象基中定义的getter,那么这就是您必须遵守的契约……在我看来,显式重写与问题(即,问题要求的内容错误)并不相关。我认为OP真正想要的是协变返回类型,这在C++/CLI(参见C2392)中不受支持,据我所知,在C#中对于抽象类(与接口相反)不受支持。@ildjarn:显式重写对于缺少协变返回来说不是一个完美的解决办法。另外,该错误消息的描述并不准确。错误消息本身是正确的:托管类型中不允许协变返回。但是描述中说,在使用
/clr
编译时不允许使用协变返回,而实际行为是,无论设置了
/clr
,本机类型都允许协变返回。抱歉,我已经厌倦了,并且误读了代码试图执行的操作。编辑,这样我可以删除否决票。