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

时间:2012-01-15 03:54:32

标签: c# class inheritance interface abstract

我有一个由几个类使用的接口,并且所有类的接口实现都是相同的。我会把它作为一个基本的抽象类,但是它会阻止派生类稍后从另一个类继承,这是我需要的。因此,不是在所有类中重新实现相同的接口,我可以在某个地方实现接口,如.h文件,并在.cs文件中包含.h文件,以便类“实现”接口。

顺便说一句,界面主要由属性组成,并在委托上更改。

4 个答案:

答案 0 :(得分:1)

编辑:根据评论划线以下 - 这可能不是你想要的。

不幸的是,除了通过一些可疑的技术(包括PostSharp之类的后期编译工具)之外,mixins不能作为C#中的内置语言功能使用。一些IoC工具也可以使混合类似的事情发生(参见Best implementation of INotifyPropertyChange ever)。

至@ 32bitkid,您可以写extension methods。它们不是接口,但它们允许您将行为的实现应用于该类型之外的类型。例如,您可以写:

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; }
}

(顺便说一下,这是auto-implemented property的一个例子)

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

您可能希望详细了解此内容,例如:http://www.csharp-station.com/Tutorials/Lesson13.aspx

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

示例:

public interface IFoo
{
    void DoSomething();
}

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

如果您现在希望SomeOtherClass具有与SomeClass相同的实现,那么您需要从SomeOtherClass派生SomeClass或重新实现它或将调用委托给{ {1}}到DoSomething的实例。另一种选择是使用像DynamicProxy这样的工具,它可以支持mixin样式。

答案 3 :(得分:0)

您基本上需要C#不支持的多重继承,但是您仍然可以在已经从另一个类派生的其他类中使用接口实现。我提出的一种方法是使用partial classesT4 Text Templates。这是一个轻微的黑客,但它比在许多派生类中复制/粘贴相同的接口实现更好。以下是一个简化示例:

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();
    }
}

DerivedClassAInterfaceImpl.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文件并指定所有派生的部分类的名称并生成multiple files