c#接口方法的默认实现

本文关键字:默认 实现 方法 接口 | 更新日期: 2023-09-27 17:49:38

是否有可能在c#中定义一个具有默认实现的接口?(这样我们就可以定义一个实现该接口的类,而不需要实现特定的默认方法)。

我知道扩展方法(如本链接所述)。但这是不是我的答案,因为有如下的方法扩展,编译器仍然抱怨在MyClass中实现MyMethod:

public interface IMyInterface
{
    string MyMethod();
}
public static class IMyInterfaceExtens
{
    public static string MyMethod(this IMyInterface someObj)
    {
        return "Default method!";
    }
}
public class MyClass: IMyInterface
{
// I want to have a default implementation of "MyMethod" 
// so that I can skip implementing it here
}

我问这个问题是因为(至少就我所知)在Java中可以这样做(见这里)。

PS:拥有一个带有某些方法的抽象基类也不是,我的答案很简单,因为我们在c#中没有多重继承,它不同于接口的默认实现(如果可能的话!)。

c#接口方法的默认实现

c# v8及以上版本允许在接口中具体实现方法。早先,抽象类只允许

这一改变现在将保护我们的具体类免受在被给定类实现后更改接口的副作用,例如,在DLL已经交付生产使用之后在接口中添加新的契约。因此,即使在实现的接口中添加了新的方法签名,我们的类仍将正确编译

现在这是可能的,因为我们还可以为引入的新合约提供默认实现。因此,我们将不必更改使用此接口的任何旧的或现有的类(参见代码片段)。

interface IA
{
    void NotImplementedMethod(); //method having only declaration
    void M() 
    { 
        WriteLine("IA.M"); 
    }//method with declaration + definition
}

原则上,我们可以说c#接口现在开始表现得像抽象类。

引用:

  • MS Docs链接- https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods
  • 你可以参考GitHub issue # 288了解实现细节。此外,Mads Torgersen在这个9频道的视频中详细讨论了这个功能。

我是一名游戏开发者,所以我经常希望为一个界面的所有实现提供通用功能,但同时也允许每个实现做自己的事情,就像子类的虚拟/覆盖方法一样。

我是这样做的:

public class Example
{
    void Start()
    {
        WallE wallE = new WallE();
        Robocop robocop = new Robocop();
        // Calling Move() (from IRobotHelper)
        // First it will execute the shared functionality, as specified in IRobotHelper
        // Then it will execute any implementation-specific functionality,
        // depending on which class called it. In this case, WallE's OnMove().
        wallE.Move(1);
        // Now if we call the same Move function on a different implementation of IRobot
        // It will again begin by executing the shared functionality, as specified in IRobotHlper's Move function
        // And then it will proceed to executing Robocop's OnMove(), for Robocop-specific functionality.
        robocop.Move(1);
        // The whole concept is similar to inheritence, but for interfaces.
        // This structure offers an - admittedly dirty - way of having some of the benefits of a multiple inheritence scheme in C#, using interfaces.
    }
}
public interface IRobot
{
    // Fields
    float speed { get; }
    float position { get; set; }
    // Implementation specific functions.
    // Similar to an override function.
    void OnMove(float direction);
}
public static class IRobotHelper
{
    // Common code for all IRobot implementations. 
    // Similar to the body of a virtual function, only it always gets called.
    public static void Move(this IRobot iRobot, float direction)
    {
        // All robots move based on their speed.
        iRobot.position += iRobot.speed * direction;
        // Call the ImplementationSpecific function
        iRobot.OnMove(direction);
    }
}
// Pro-Guns robot.
public class Robocop : IRobot
{
    public float position { get; set; }
    public float speed { get; set;}
    private void Shoot(float direction) { }
    // Robocop also shoots when he moves
    public void OnMove(float direction)
    {
        Shoot(direction);
    }
}
// Hippie robot.
public class WallE : IRobot
{
    public float position { get; set; }
    public float speed { get; set; }
    // Wall-E is happy just moving around
    public void OnMove(float direction) { }
}

简短回答:

不,你不能在接口中编写方法的实现。

描述:

接口就像契约一样,所以从它继承的类型必须定义实现,如果你有一个场景,你需要一个默认实现的方法,那么你可以让你的类抽象,并为你想要的方法定义默认实现。

例如:

public abstract class MyType
{
    public string MyMethod()
    {
      // some implementation
    }
    public abstract string SomeMethodWhichDerivedTypeWillImplement();
}

和现在的派生类:

public class DerivedType : MyType
{
  // now use the default implemented method here
}

UPDATE (c# 8将支持此功能):

c# 8将允许在接口
中有默认实现

不是直接的,但是您可以为接口定义一个扩展方法,然后像这样实现它

public interface ITestUser
{
    int id { get; set; }
    string firstName { get; set; }
    string lastName { get; set; }
    string FormattedName();
}
static class ITestUserHelpers
{
    public static string FormattedNameDefault(this ITestUser user)
    {
        return user.lastName + ", " + user.firstName;
    }
}
public class TestUser : ITestUser
{
    public int id { get; set; }
    public string firstName { get; set; }
    public string lastName { get; set; }
    public string FormattedName()
    {
        return this.FormattedNameDefault();
    }
}

编辑*重要的是,扩展方法和您正在实现的方法的命名不同,否则您可能会得到stackoverflow。

在c# 8.0中是可能的。您可以添加具有默认实现的方法。您必须将目标框架版本更改为最新版本才能使用此功能。

c# 11特性-现在正式发布:

静态虚成员

文档说:

c# 11和。net 7在接口中包含了静态虚成员。

该特性使您能够定义包含重载的接口操作符或其他静态成员。一旦定义了带有静态成员的接口,就可以使用这些接口作为约束来创建使用操作符或其他静态方法的泛型类型。

所以你可以:

定义带有静态成员的接口

使用接口定义类,这些类实现带有已定义操作符的接口。

创建依赖静态接口方法的泛型算法。

https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/static-virtual-interface-members

先决条件

你需要设置你的机器运行。net 7,它支持c# 11

作为一个c#编程新手,我正在阅读这个主题,想知道下面的代码示例是否有任何帮助(我甚至不知道这是否是正确的方法)。对我来说,它允许我在接口背后编写默认行为。注意,我使用泛型类型规范来定义一个(抽象)类。

namespace InterfaceExample
{
    public interface IDef
    {
        void FDef();
    }
    public interface IImp
    {
        void FImp();
    }
    public class AbstractImplementation<T> where T : IImp
    {
        // This class implements default behavior for interface IDef
        public void FAbs(IImp implementation)
        {
            implementation.FImp();
        }
    }
    public class MyImplementation : AbstractImplementation<MyImplementation>, IImp, IDef
    {
        public void FDef()
        {
            FAbs(this);
        }
        public void FImp()
        {
            // Called by AbstractImplementation
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyImplementation MyInstance = new MyImplementation();
           MyInstance.FDef();
        }
    }
}