我可以在.h文件中的C#中实现一个接口吗

本文关键字:一个 接口 实现 文件 我可以 | 更新日期: 2023-09-27 18:20:15

我有一个由多个类使用的接口,并且所有类的接口实现都是相同的。我会让它成为一个基本抽象类,但它会阻止派生类稍后从另一个类继承,这是我需要的。因此,与其在所有类中重新实现相同的接口,我可以在一个地方以某种方式实现接口吗,比如一个.h文件,并将.h文件包括在cs文件中,这样类就可以"实现"接口。

顺便说一句,接口主要由属性组成,并在委托时进行了更改。

我可以在.h文件中的C#中实现一个接口吗

我对C#有点生疏,所以肯定有一种特定于C#的方法可以做到这一点。但是,从更一般的意义上讲,您可以在它自己的标准类文件中提供实现。对于每个需要实现接口的类,您仍然需要声明接口方法,但您可以对共享的"include"实现进行单行调用,而不是将冗长的实现复制并粘贴到每个类中。

(这可能不是最好的解决方案,但应该是一个可行的方案,至少可以让你开始。)

C#没有头文件的概念。在C#中你不可能轻易做到这一点。如果您实现了一个接口,并且希望在另一个类中具有相同的实现,那么另一个类别需要从实现类别派生。

示例:

public interface IFoo
{
    void DoSomething();
}
public class SomeClass : IFoo
{
    public void DoSomething()
    {
    }
}

如果您现在想要具有与SomeClass具有相同实现的SomeOtherClass,那么您需要从SomeClass派生SomeOtherClass,或者重新实现它,或者将对DoSomething的调用委托给SomeClass的实例。另一种选择是使用类似DynamicProxy的工具,它可以支持mixin样式。

EDIT:根据注释,删除行下的所有内容,这可能不是您想要的。

不幸的是,除了通过一些有问题的技术(包括PostSharp等编译后工具)之外,混合插件并不能作为C#中的内置语言功能使用。一些IoC工具也可以使类似mixin的事情发生(请参阅INotifyPropertyChange的最佳实现)。

就@32bitkid而言,您可以编写扩展方法。它们不是接口,但允许您将行为的实现从该类型外部应用到该类型。例如,你可以写:

public static class IPersonExtensions {
    // Note use of this keyword
    public static Int32 GetAge(this IPerson p) { return DateTime.Now - p.BirthDate; }
}

然后这样使用:

var p = new Person( ... );
var pAge = p.GetAge();

是的,接口通常就是这样使用的——尽管它们得到的是.cs文件,而不是.h文件。您可以在它自己的文件中定义接口,就像类一样,然后将类声明为实现接口。

例如,在IFoo.cs:中

public interface IFoo {
  public String Bar { get; set; }
}

然后在ConcreteFoo.cs:中

public class ConcreteFoo : IFoo {
  // This property implements IFoo.Bar
  public String Bar { get; set; }
}

(顺便说一句,这是一个自动实现属性的例子)

从技术上讲,IFoo甚至不需要在它自己的文件中——它可以在任何.cs文件中。按照惯例,它通常是自己的。另外,请注意接口使用I前缀的约定。

你可能想阅读更多关于这方面的内容,例如:http://www.csharp-station.com/Tutorials/Lesson13.aspx

您基本上需要C#不支持的多重继承,但是您仍然可以在已经从另一个类派生的其他类中使用接口实现。我想到的一种方法是使用分部类和T4文本模板。这是一个轻微的破解,但它比在许多派生类中复制/粘贴相同的接口实现要好。下面是一个简化的例子:

IInterface.cs

public interface IInterface
{
    void Foo();
}

InterfaceImpl.cs

public partial class InterfaceImpl : IInterface
{
    public void Foo()
    {
        Console.WriteLine("Foo");
    }
}

BaseClass.cs

using System;
public class BaseClass
{
    public void Bar()
    {
        Console.WriteLine("Bar");
    }
}

DerivedClassA.cs

public partial class DerivedClassA : BaseClass, IInterface
{
    public void FooBar()
    {
        this.Foo();
        this.Bar();
    }
}

派生类接口Impl.tt

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<# var codeText = System.IO.File.ReadAllText(this.Host.ResolvePath("InterfaceImpl.cs")).Replace("InterfaceImpl", "DerivedClassA"); #>
<#= codeText #>

DerivedClassB.cs

 public partial class DerivedClassB : BaseClass, IInterface
    {
        public void BarFoo()
        {
            this.Bar();
            this.Foo();
        }
    }

DerivedClassBInterfaceImpl.tt

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<# var codeText = System.IO.File.ReadAllText(this.Host.ResolvePath("InterfaceImpl.cs")).Replace("InterfaceImpl", "DerivedClassB"); #>
<#= codeText #>

有点烦人的是,这需要为每个想要使用接口实现的派生类创建一个tt文件,但如果InterfaceImpl.cs是几行以上的代码,它仍然可以节省复制/粘贴代码。也可能只创建一个tt文件,指定所有派生的分部类的名称,并生成多个文件。