C# 为什么可以';我不能在接口上调用ToString()吗?

C# 为什么可以';我不能在接口上调用ToString()吗?,c#,vb.net,C#,Vb.net,我在一个示例控制台应用程序中重新创建它时遇到了不同的问题,所以我非常有兴趣知道发生了什么 最初的问题是,在我的代码中,我有一个名为ICat的类,这个类是用C编写的# 在同一程序集中,在C#中,有一个实现: public class MagicCat : ICat { public string ToString(CatColour colour) { return $"I am a {colour} cat"; } } 这

我在一个示例控制台应用程序中重新创建它时遇到了不同的问题,所以我非常有兴趣知道发生了什么

最初的问题是,在我的代码中,我有一个名为
ICat
的类,这个类是用C编写的#

在同一程序集中,在C#中,有一个实现:

public class MagicCat : ICat
{
        public string ToString(CatColour colour)
        {
            return $"I am a {colour} cat";
        }
}
这个编译没有任何问题

在另一个用VB.NET编写的程序集中,我有以下代码:

Dim myCat As ICat = GetCat()
Dim result = myCat.ToString() ' Error on this line
public class Cat : IAnimal
{
    public string ToString(CatColour colour)
    {
        return $"I am a {colour} cat.";
    }

    //public string ToString()
    //{
    //    return "I am a cat.";
    //}
}

public interface IAnimal
{
    string ToString(CatColour colour);
}

class Program
{
    static void Main(string[] args)
    {
        IAnimal cat = new Cat();

        Console.WriteLine(new Cat().ToString());
        Console.WriteLine(new Cat().ToString(CatColour.Red));

        Console.WriteLine(cat.ToString());
        Console.WriteLine(cat.ToString(CatColour.Blue));

        Console.ReadKey();
    }
}

public enum CatColour
{
    Red = 1,
    Blue = 2
}
这会导致编译器错误,称“函数ToString(格式为AddressFormat)为String”的参数“Color”未指定
参数。

我尝试在C#应用程序中重新创建此代码:

Dim myCat As ICat = GetCat()
Dim result = myCat.ToString() ' Error on this line
public class Cat : IAnimal
{
    public string ToString(CatColour colour)
    {
        return $"I am a {colour} cat.";
    }

    //public string ToString()
    //{
    //    return "I am a cat.";
    //}
}

public interface IAnimal
{
    string ToString(CatColour colour);
}

class Program
{
    static void Main(string[] args)
    {
        IAnimal cat = new Cat();

        Console.WriteLine(new Cat().ToString());
        Console.WriteLine(new Cat().ToString(CatColour.Red));

        Console.WriteLine(cat.ToString());
        Console.WriteLine(cat.ToString(CatColour.Blue));

        Console.ReadKey();
    }
}

public enum CatColour
{
    Red = 1,
    Blue = 2
}
它编译并运行,输出为:

控制台应用程序1.Cat
我是一只红猫。
控制台应用程序1.Cat
我是一只蓝色的猫

(如果我取消对另一个ToString()方法的注释,第一行将改为
>我是一只猫。

这正是我所期望的

我将应用程序转换为VB.NET,希望得到上面的原始错误,但我得到了以下问题:

Public Class Cat
    Implements IAnimal
    Public Function ToString(colour As String) As String
        Return "I am a {colour} cat."
    End Function
End Class

Public Interface IAnimal
    Function ToString(colour As String) As String
End Interface
类“Cat”必须为接口“IAnimal”实现“函数ToString(颜色为String)为String”

那么这里发生了什么?为什么VB.NET在我的接口实现中给了我一个错误,为什么我的原始场景抱怨no-ToString()方法不带参数


编辑:我已将我的vb代码更新为:

Public Interface IAnimal
    Function ToString(colour As String) As String
End Interface

Public Class Cat
    Implements IAnimal
    Public Function ToString(colour As String) As String Implements IAnimal.ToString
        Return "I am a {colour} cat."
    End Function
End Class

Sub Main()

    Dim cat As Cat = New Cat()
    Dim icat As IAnimal = New Cat()

    Call cat.ToString()
End Sub

对于“Public Function ToString(color As String)As String”的参数“color”,我没有指定
参数,这是C代码中没有出现的原始问题。知道为什么吗?Cat是一个对象,因此其上有一个空白的
ToString()
方法。

您必须添加更多信息:

Public Class Cat
     Implements IAnimal
     Public OverLoads Function ToString(colour As String) As String Implements IAnimal.ToString
         Return $"I am a {colour} cat."
     End Function
End Class

Public Interface IAnimal
    Function ToString(colour As String) As String
End Interface


您可能希望为带参数的
ToString()
声明
重载
(因为您有另一个从
对象
派生的基本
ToString()
),并
覆盖从
对象
派生的不带参数的
ToString()

Public Class Cat
    Implements IAnimal
    Public Overloads Function ToString(colour As String) As String Implements IAnimal.ToString
        Return "I am a {colour} cat."
    End Function
    Public Overrides Function ToString()
        Return "I am a cat."
    End Function
End Class

Public Interface IAnimal
    Function ToString(colour As String) As String
End Interface
或者,您可以为
IAnimal
创建两个
ToString()
,并重写
ToString()
,而不使用
IAnimal
中的参数,而不是
对象中的参数

Public Class Cat
    Implements IAnimal
    Public Overloads Function ToString(colour As String) As String Implements IAnimal.ToString
        Return "I am a {colour} cat."
    End Function
    Public Overrides Function ToString() As String Implements IAnimal.ToString
        Return "I am a cat."
    End Function
End Class

Public Interface IAnimal
    Function ToString(colour As String) As String
    Function ToString() As String
End Interface

您需要显式地实现接口方法。为什么我不能在接口上调用ToString(),可能是因为接口不是从对象继承的。在C#版本中,您已经定义了“ToString”方法的版本,一个带参数,一个不带任何参数。但在VB版本中,只有参数版本存在。我认为你也需要覆盖这个。这意味着需要显式实现。我想你可能会说,为什么VB.NET要我在接口中添加
ToString()
,以便它可以调用,而C#在
ToString()时却没有
对象的一种方法,而
Cat
是对象吗?注意:我原以为您希望在返回的字符串前面有一个
$
,这样字符串中的颜色实际上会被替换(很高兴看到知道如何拼写颜色的人)。我发现您的问题有一个解决方案。虽然这是一个有效的问题,但我不会将接口成员命名为
ToString
,即使使用不同的签名,因为使用
ToString()啊哈!这使得VB.NET部分的行为符合我的预期。但是,它不允许我在没有参数的情况下调用
ToString()
,即使执行
New Cat()。ToString()
正确地向字符串添加重载可能也会阻止完全调用工具的需要……添加
重载似乎已经解决了问题。我很想知道为什么VB.NET中需要这个,我没有办法将它添加到我原来的问题中的接口中,因为它是用C#编写的,并且没有这样的关键字。这是因为你重载了在基类(对象)中定义的函数。我想这是VB.NET的一个怪癖,需要指定它。有趣的是,如果您在C#汇编中实现一个接口,这是一个突破性的问题。在我的例子中,我可以编辑引用的程序集以添加另一个
ToString()
实现,并重新发布NuGet包,该包仍然存在漏洞,但如果它是第三方方法,我将无法在VB.NET中正确使用它。想不到。我认为这是必需的。无法重写它(即使编译器发出警告说它需要重写),因为如果我这样做,我收到一个错误,说没有一个函数可以用该签名重写。显然,
重载了
关键字可以修复它,但由于我的界面是C#程序集,因此无法添加关键字,因此VB.NET可以很好地运行。