如何解决这个 c# 语法难题

本文关键字:语法 难题 何解决 解决 | 更新日期: 2023-09-27 18:32:32

有人可以给我以下代码难题的解决方案吗?给出了一个解决方案,但可能是多个解决方案。

// this code compiles
IAnimal animal= new Dog();
animal.Eat();
// this code doesn't compile
Dog animal = new Dog();
animal.Eat();

类定义应该是什么样子的,以便上面的代码块在不同的范围内编译(第一个(和不编译(第二个(?

如何解决这个 c# 语法难题

您可以通过使用显式接口实现来实现此目的:

class Dog : IAnimal {
    void IAnimal.Eat(){
        //do stuff
    }
}

与隐式接口实现相反:

class Dog : IAnimal {
    public void Eat(){
        //do stuff
    }
}
public interface IAnimal
{
    void Eat();
}
public class Dog : IAnimal
{
    void IAnimal.Eat() { }
}

IAnimal animal = new Dog();
animal.Eat(); // <---- OK
Dog animal2 = new Dog();
animal2.Eat(); // <---- COMPILE ERROR

导致第二行的错误是因为类Dog显式实现了IAnimal接口,如下所示:

class Dog : IAnimal
{
    void IAnimal.Eat()
    {
        throw new NotImplementedException();
    }
}

在这种情况下,您会在第二行收到编译错误,因为除非您正在使用IAnimal实例,否则您无法调用Eat因为它本质上是 Dog 中的私有方法。

要修复此错误,您需要将实例强制转换为我上面向您展示的IAnimal,或者您可以隐式实现如下所示的接口:

class Dog : IAnimal
{
    public void Eat()
    {
        throw new NotImplementedException();
    }
}

显而易见的解决方案(IAnimal接口,Dog是显式实现该接口的类(已经在其他答案中提供了。

以下是我能想到的其他一些方法。

所有这些都是基于IAnimal像这样的(名称不佳的(类

public class IAnimal
{
    public void Eat() { }
}
(

A(基于类定义隐式转换运算符的解决方案(请注意,禁止定义从类到接口的转换,这就是为什么IAnimal成为类/结构很重要的原因(

public class Dog
{
    public static implicit operator IAnimal(Dog dog) { return new IAnimal(); }
}

在第二个代码段中导致以下编译错误:

错误 CS1061:"Dog"不包含"Eat"的定义,并且找不到接受类型为"Dog"的第一个参数的扩展方法"Eat"(是否缺少 using 指令或程序集引用?

(B(基于基本方法隐藏的解决方案。尽管在 C# 中我们不能通过在派生类中提供另一个具有不同签名的方法来隐藏基方法(因为它将被视为重载(,但我们可以通过使用具有不兼容签名的字段属性事件来做到这一点。

例如

public class Dog : IAnimal
{
    new public event Action Eat;
}

生成

错误 CS0070:事件"Dog.Eat"只能出现在 += 或 -= 的左侧(除非在类型"Dog"中使用(

public class Dog : IAnimal
{
    new public Action<int> Eat;
}

生成

错误 CS7036:没有给出与"操作"的必需形式参数"obj"对应的参数