C#接口的方法的默认实现?

Ali*_*ili 31 c# oop interface

是否可以在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
}
Run Code Online (Sandbox Code Playgroud)

我问这个是因为(至少据我所知)可以用Java实现(见这里).

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

Kon*_*dis 32

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

我是这样做的:

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) { }
}
Run Code Online (Sandbox Code Playgroud)

  • @Jazimov - 建议的体系结构提供跨接口实现具有通用功能的能力.IRobotHelper保存公共部分,以便每个实现只需要实现特定于实现的部分.在这个例子中,如果你有一个Robocop或WallE类型的对象r,或任何其他实现IRobot的类,你调用r.Move(1)它将首先从IRobotHelper调用共享函数Move(这个IRobot),这将反过来调用特定于实现的OnMove(1)对应的IRobot实现.这对你有意义吗? (10认同)
  • 我在你的例子中没有看到`IRobotHelper`的使用.它的目的是什么? (6认同)
  • 如果你想知道我是怎么回事,怎么可能在`IRobot`上调用`Move()`,它被称为[扩展方法](https://docs.microsoft.com/en-us/dotnet/ CSHARP /编程导/类和 - 结构/延伸的方法) (3认同)
  • @KonstantinosVasileiadis 标准命名是“RobotExtensions”。当然,这并不重要。 (3认同)

RBT*_*RBT 28

C#v8也将开始允许在接口中实现具体方法.这将允许您在更改将来实现的接口时不会破坏具体的实现类.

所以这样的东西在下一个语言版本中是可能的:

interface IA
{
    void NotImplementedMethod();
    void M() { WriteLine("IA.M"); } //method definition present in the interface
}
Run Code Online (Sandbox Code Playgroud)

请参阅此GitHub 问题#288.Mads Torgersen也在这个频道9视频中详细讨论了这个即将推出的功能.

注意:在编写此答案时,RTM状态的当前版本的C#语言是v7.


Ehs*_*jad 15

简答:

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

描述:

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

例如:

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

    public abstract string SomeMethodWhichDerivedTypeWillImplement();
}
Run Code Online (Sandbox Code Playgroud)

现在在Dervied班:

public class DerivedType : MyType
{
  // now use the default implemented method here
}
Run Code Online (Sandbox Code Playgroud)

更新(C#8将支持此):

C#8允许在接口中使用默认实现

  • 希望我们能在c#8.0中得到它 (6认同)

Tim*_*m M 6

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑*重要的是,您实现的扩展方法和方法的命名方式不同,否则您可能会获得堆栈溢出.


小智 6

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