无法编译C#默认接口方法

3
C# 8.0有一个新功能,允许您在接口方法中添加默认实现。我要么做错了什么,要么这个功能不像广告中宣传的那样工作。(我猜是前者。)
我创建了一个新的.NET Core 3.1控制台应用程序,并编写了以下代码:
using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var xxx = new MyClass { MyInt = 5 };
            Console.WriteLine(xxx.GetItNow());
        }
    }

    public interface ITest
    {
        int MyInt { get; set; }
        int GetItNow() => MyInt * 2;
    }

    public class MyClass : ITest
    {
        public int MyInt { get; set; }
    }
}

"

Console.WriteLine(xxx.GetItNow()));语句无法编译,因为

MyClass没有定义'GetItNow()'...

所以编译器认为MyClass并没有明确引用GetItNow()(它并不会抱怨MyClass没有实现接口)。但是它并不将默认接口成员视为实现接口的类的公共方法。

我有什么遗漏,还是出了什么问题?

"

3
Console.WriteLine((xxx as ITest).GetItNow())); 这段代码中的默认接口方法属于接口而不是实现它的类,所以必须使用强制类型转换(如 xxx as ITest) 。另外一种选择是声明 xxx 为接口类型,例如 ITest xxx = new MyClass { MyInt = 5 };。请注意,这仅仅是将 xxx 声明为接口类型,并不会改变其实际类型。 - Dmitry Bychenko
1
哦!谢谢!是的,“文档”(实际上是一个过于复杂的教程)提到了这样一个事实,即为了访问默认接口成员,必须将对象引用转换为接口。所以这个可以编译通过:Console.WriteLine(((ITest)xxx).GetItNow()); - Bob.at.Indigo.Health
2个回答

8

好的,接口默认方法属于接口而不属于实现它的,因此您有两个选择:

强制转换:

  Console.WriteLine(((ITest)xxx).GetItNow()));

声明变更(优先使用; MyClass实现细节,通常是依赖项; ITest - 契约才是真正重要的事情):

  ITest xxx = new MyClass { MyInt = 5 };
  // xxx is ITest, so xxx.GetItNow() is legal now 
  Console.WriteLine(xxx.GetItNow());

我建议使用第二种方法 - 那个在编译时是安全的! - Julian

0

https://dev59.com/lLroa4cB1Zd3GeqPtOXX#61717913 是一篇非常出色和清晰的答案,我曾试图使用这个新功能来实现相同的效果,但被编译器阻止了。现在我知道原因了。

如果你的意图是标记某个类并附加一些功能。我一直在使用接口本身的扩展方法来实现这种效果。唯一的缺点是目前仅支持函数而不支持属性。

public interface ITest
{
    int MyInt { get; set; }
}

public static class ITestExtensions
{
    public static int GetItNow(this ITest self)
    {
        return self.MyInt * 2;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接