C#接口和实现在同一个文件中 - 好主意?

Pau*_*aul 30 c#

我最近看到一些C#代码,其中的接口声明和实现位于同一个文件中,就像这样

namespace MyNameSpace.Foo
{
    public interface IFoo{
        void DoThis();
    }
    public class Foo : IFoo {
        public void DoThis();
    }
}
Run Code Online (Sandbox Code Playgroud)

乍一看,在同一个文件中声明和实现似乎都是错误的,但是有实际的好处.例如,当您在Visual Studio中转到定义时,接口和实现位于同一文件中.此方法不会禁止您使用其他接口实现,例如单元测试可能需要.对于只有一个实现的接口,我认为这可能是一种实用的方法.

好主意还是坏主意?

扩展问题:
当您有接口引用时,人们如何使用Visual Studio导航到实现IFoo myFoo = FooFactory.getFoo(MY_FOO);如果我右键单击IFoo并选择Go To Definition我可以获得接口声明.有没有办法让我获得IFoo的实现列表,因为这是我真正感兴趣的内容.

Ric*_*ett 40

我的建议是始终遵循每个.cs文件中一个项目的规则,无论是枚举声明,接口还是类..cs文件的名称应与其包含的内容的名称匹配.

简单的规则,易于遵循.我们在内部使用StyleCop对此进行监管.

如果将此方法与名称空间的合理使用相结合,那么它应该意味着Visual Studio中的解决方案资源管理器视图可以轻松导航项目中的组件.请注意,ReSharper为此导航提供了另一种方法,但使用它并不是每个人的口味(并不是每个人都可能有一个插件,如ReSharper).

Travis G已经询问了诸如委托和自定义EventArgs声明之类的细节.由于自定义EventArgs是类,我会将它们放在自己的文件中(同样,保持规则简单).代表我会向使用它们的类声明.如果我发现我在很多地方使用了很多委托,我可以考虑将它们全部放在Delegates.cs文件中(我有时会在常量中使用Consts.cs文件).

然而,其中一些肯定是主观的,并进入软件宗教战争的领域.

  • 我支持这个。它简化了代码浏览以及特定类或接口的搜索:只需查看文件名。 (2认同)
  • 我和你在一起,但是对于诸如`委托和自定义`EventArg`s这样的小事情你做了什么?我通常将它们放在同一个文件中,因为它们只在一个地方使用. (2认同)

UpT*_*eek 19

亲身...

如果一个接口很可能(在短期内)用于一个类(比如提供依赖注入的接口),那么我将把它放在类文件的顶部.在开发期间(当班级可能正在改变时),每次公共场地变化时,PITA都必须更改两个文件.

当然,如果接口有可能由多个类实现,那么我将它放在一个单独的文件中.

  • @ChrisMarisic如果所说的依赖项不是接口,你会如何为单元测试提供依赖的模拟? (11认同)
  • 是的,这是我想到的场景,当你只是出于DI的原因而使用接口时,除了测试impl之外你没有太多机会实现接口的另一个定义. (4认同)
  • `如果一个接口只可能用于一个类`你做错了.界面在这里毫无价值.如果多个类没有立即实现接口,那么你做错了.依赖注入不需要无意义的接口.这是一个神话.使用实际的具体类型. (3认同)
  • 这在VS2017中不再是一个大问题.您现在[接口/类声明旁边的侧边栏上的图标](http://imgur.com/gLUyPjO)允许您在它们之间来回导航. (2认同)

Rub*_*ias 9

将接口定义和实现放在同一个文件中与单元测试无关,因为该接口无论如何都是可用的.

我通常从相同文件的简单接口和实现开始.当事情成长时,我会在其他代码需要引用该接口时拆分它们.


maf*_*afu 5

我认为这是一个坏主意.

保持接口和实现分离.否则你有可能弄乱设计.包括文件并自动获取实现,即使你只需要接口,然后意外(因为它很方便)使用Impl而不是接口和yay,紧耦合.