Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 向接口添加新函数_C#_Interface_Overloading - Fatal编程技术网

C# 向接口添加新函数

C# 向接口添加新函数,c#,interface,overloading,C#,Interface,Overloading,我需要为现有接口上的函数创建重载,而不影响当前实现或使用接口的任何组件(理想情况下) 我想我有几个选择: 简化 原始接口: 我可以向接口添加新的重载函数,并强制实现接口的每个类实现新函数 public interface IServerComponent { bool Add(int a, int b); bool Add(int a, int b, int c); } 或者我可以创建一个实现原始接口的新接口。然后,使用原始接口的其他类将不需要更改,任何新类都可以实现新接口 p

我需要为现有接口上的函数创建重载,而不影响当前实现或使用接口的任何组件(理想情况下)

我想我有几个选择:

简化 原始接口:

我可以向接口添加新的重载函数,并强制实现接口的每个类实现新函数

public interface IServerComponent
{
    bool Add(int a, int b);
    bool Add(int a, int b, int c);
}
或者我可以创建一个实现原始接口的新接口。然后,使用原始接口的其他类将不需要更改,任何新类都可以实现新接口

public interface IServerComponent2 : IServerComponent
{
    bool Add(int a, int b, int c);
}
这种情况下的最佳做法是什么?还有其他选择吗


谢谢

如果新方法可以用旧方法表示,您可以使用扩展方法:

// Original interface
public interface IServerComponent 
{ 
  bool Add(int a, int b, int c); 
} 

// New overload
public static class MyServerMethods
{
  public static bool Add(this IServerComponent component, int a, int b)
  {
    return component.Add(a, b, 0);
  }
}

如果方法不能这样表达(即,它们确实需要由组件本身实现),那么我建议定义一个新接口。此方法具有最大的向后兼容性。

如果您的IServerComponent接口尚未发布,或者是仅由您自己的类实现的内部接口,并且新的接口成员对实现该接口的所有现有类都有意义,请更改现有接口

否则,创建扩展IServerComponent的IServerComponent2接口。IIRC这是框架设计指南的建议。可以在.NET Framework中以类的形式找到这方面的示例

但是,如果新成员可以按照原始成员的方式实现,您还可以使用:


这取决于上下文——如果有许多类实现了原始接口,或者如果它已发布,那么唯一实用的方法就是引入新接口。另一方面,从长远来看,只有一个接口要干净得多,所以如果你负担得起,我会说重构现有的接口。

如果你不需要或不想更改已经实现旧接口的类(现在或将来),你应该创建第二个接口。然而,它感觉更像是一种黑客行为,可能会给你带来不那么直观的代码


另外,根据我的经验,推迟重构从来都不是一个好主意。因此,如果您怀疑以后需要实现该接口,那么不妨修改现有接口,省去一些麻烦。这绝对是一种更干净的方法。

我认为维护一个接口更容易,但第二种方法使用两个接口更好,因为不是每个类都需要实现bool Add(inta、intb、intc)

我意识到你的例子是做作的,但我想给你一个做作的答案,与你所表达的不同,这样也许你可以用不同的方式来思考它。与其让您的接口方法对具体的东西进行操作,不如让它对抽象的东西进行操作

比如说

public interface IAddableThings
{
  int a;
  int b;
}

public interface IOtherAddableThings : IAddableThings
{
  int a;
  int b;
}

public interface IServerComponent
{
    bool Add(IAddableThings things);
}
如果这真的是一个Add,那么我认为这更有意义,但是如果它真的更像Calculate(),那么您将希望将部分或所有方法操作向下移动到IAddableThings对象

public interface IAddableThings
{
  int a;
  int b;
  bool CalculateMe();
}

扩展方法会起作用,但也会将实现类的功能扩展到其他类,从而降低内聚性。我认为这充其量只是一个临时解决办法。如果您无法扩展类,因为您没有访问源的权限,那么扩展方法就有意义了。我可能这样做是为了对现有代码库进行一些小的更新,但我肯定会把它放在下一个主要版本的重构列表中。这完全取决于设计。如果您正在添加新功能,那么我会同意;它属于一个接口。如果您正在添加重载(例如,几乎相同的功能,总是可以用其他功能表达),那么我不同意。在这种情况下,扩展方法允许正交性,减少代码重复。关于这个主题有一篇很好的博文。@Stephen-非常有趣!然而,虚拟调度问题让我感到恐惧。除了最简单的项目外,我认为C#对这一点的支持还不足以在所有项目中使用——它只是过度提升了代码熵(并有可能降低内聚性,尽管在我们正在考虑的简单案例中肯定不是如此。)@Jeff:Joe Duffy的帖子比C#真正支持的(我支持的)更深入。C++支持完全的“静态多态”,因为它有模板;在这方面,C#仍然缺乏。然而,正交性仍然是可能的和重要的。它真的会降低凝聚力吗?我说“不”。现代API(LINQ、TPL、Rx)都定义了要实现的“最小接口”,并提供了库作为扩展方法的真正功能。我们正在慢慢地重新发明C++的正交设计。STL@Stephen-有些情况下,通过扩展方法添加功能会增加可理解性(例如,请参阅MVC中的HtmlHelper扩展),但在一般情况下,我不希望必须导航到其他类才能理解我正在使用的类上的方法。我投票支持这个答案正是因为您引用的特定用例和您对新功能的评论,但我仍然会在一个主要版本中进行重构,将新类的所有代码放在一个地方。
public interface IAddableThings
{
  int a;
  int b;
}

public interface IOtherAddableThings : IAddableThings
{
  int a;
  int b;
}

public interface IServerComponent
{
    bool Add(IAddableThings things);
}
public interface IAddableThings
{
  int a;
  int b;
  bool CalculateMe();
}