【问题标题】:Can I implement an interface in a C# in an .h file?我可以在 .h 文件中的 C# 中实现接口吗?
【发布时间】:2012-01-15 03:54:32
【问题描述】:

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

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

【问题讨论】:

  • 我没有时间写一个真正的答案,但是接口可以有扩展方法。这可能符合您的要求,但这取决于您要做什么
  • @32bitkid 谢谢,我去看看。
  • 如果扩展方法不能满足您的需求,请尝试将接口实现分解为一个单独的类,该类将包含对您的几个类之一的包装对象的引用。根据您要执行的操作,您可能能够提供对包装对象的访问,例如通过IServiceProvider

标签: c# class inheritance interface abstract


【解决方案1】:

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

(这可能不是最好的解决方案,但应该是一个可行的解决方案,至少可以帮助您入门。)

【讨论】:

  • 我建议您使用结构而不是类来避免额外分配。
【解决方案2】:

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

例子:

public interface IFoo
{
    void DoSomething();
}

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

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

【讨论】:

    【解决方案3】:

    编辑:划线以下的所有内容 - 根据 cmets,这可能不是您想要的。

    不幸的是,除了通过一些有问题的技术,包括像PostSharp 这样的后编译工具外,mixin 不能作为 C# 的内置语言功能使用。一些 IoC 工具也可以让类似 mixin 的事情发生(参见 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

    【讨论】:

    • 操作者想知道如何编写一个mixin,而不是如何使用一般的接口。
    【解决方案4】:

    您基本上需要 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

    【讨论】:

      猜你喜欢
      • 2021-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-10
      • 2012-07-07
      • 2018-05-10
      • 2018-04-04
      • 2021-02-03
      相关资源
      最近更新 更多