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

时间:2016-01-29 19:37:07

标签: c# .net logic

有人可以给我以下代码拼图的解决方案吗? 给出了一个解决方案,但可能不止一个解决方案。

// this code compiles
IAnimal animal= new Dog();
animal.Eat();

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

如何将类定义看起来如此,以便上面的代码在不同的作用域中编译(第一个)并且不编译(第二个)?

4 个答案:

答案 0 :(得分:4)

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

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

与隐式接口实现相反:

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

答案 1 :(得分:3)

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

答案 2 :(得分:3)

第二行的错误是由于类Dog 显式实现IAnimal接口而导致的错误:

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

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

要修复错误,您需要将实例转发回IAnimal,就像我上面展示的那样,或者您可以隐式实现这样的界面:

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

答案 3 :(得分:2)

显而易见的解决方案(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'的定义,并且没有扩展方法'Eat'可以找到接受'Dog'类型的第一个参数(你是否缺少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:没有给出对应于'Action'所需的形式参数'obj'的参数