Kei*_*ith 24 c# extension-methods .net-3.5
.Net 3.5中的新扩展允许从接口拆分功能.
例如在.Net 2.0中
public interface IHaveChildren {
string ParentType { get; }
int ParentId { get; }
List<IChild> GetChildren()
}
Run Code Online (Sandbox Code Playgroud)
可以(在3.5中)成为:
public interface IHaveChildren {
string ParentType { get; }
int ParentId { get; }
}
public static class HaveChildrenExtension {
public static List<IChild> GetChildren( this IHaveChildren ) {
//logic to get children by parent type and id
//shared for all classes implementing IHaveChildren
}
}
Run Code Online (Sandbox Code Playgroud)
在我看来,这对于许多接口来说是更好的机制.他们不再需要抽象基础来共享此代码,并且功能上代码的工作原理相同.这可以使代码更易于维护和更容易测试.
唯一的缺点是抽象基础实现可以是虚拟的,但可以解决(实例方法是否会隐藏具有相同名称的扩展方法?这会使代码混淆吗?)
没有经常使用这种模式的任何其他原因?
澄清:
是的,我看到扩展方法的趋势是到处都是它们.如果没有大量的同行评审,我会特别小心使用.Net值类型(我认为我们在字符串上唯一的一个是.SplitToDictionary()- 类似于.Split()但也采用键值分隔符)
我认为那里有一个完整的最佳实践辩论;-)
(顺便说一下:DannySmurf,你的PM听起来很可怕.)
我在这里特别询问使用扩展方法,以前我们有接口方法.
我试图避免许多级别的抽象基类 - 实现这些模型的类大多已经有了基类.我认为这个模型可以比添加更多的对象层次结构更易于维护和更少过度耦合.
这是MS对Linq的IEnumerable和IQueryable做了什么?
Jon*_*jap 11
扩展方法应该只用作:扩展.任何关键的结构/设计相关代码或非平凡操作都应该放在一个由类或接口组成/继承的对象中.
一旦另一个对象尝试使用扩展的对象,他们将看不到扩展,并且可能必须再次重新实现/重新引用它们.
传统观点认为,扩展方法只应用于:
我认为明智地使用扩展方法会将接口置于与(抽象)基类更加相等的位置.
版本.基类具有过多接口的一个优点是,您可以在更高版本中轻松添加新虚拟成员,而向接口添加成员将破坏针对旧版本库构建的实现者.相反,需要创建具有新成员的新版本的接口,并且库必须解决或限制对仅实现原始接口的旧对象的访问.
作为一个具体的例子,库的第一个版本可能定义如下的接口:
public interface INode {
INode Root { get; }
List<INode> GetChildren( );
}
Run Code Online (Sandbox Code Playgroud)
库已发布后,我们无法在不破坏当前用户的情况下修改界面.相反,在下一个版本中,我们需要定义一个新接口来添加其他功能:
public interface IChildNode : INode {
INode Parent { get; }
}
Run Code Online (Sandbox Code Playgroud)
但是,只有新库的用户才能实现新接口.为了使用遗留代码,我们需要调整旧的实现,扩展方法可以很好地处理:
public static class NodeExtensions {
public INode GetParent( this INode node ) {
// If the node implements the new interface, call it directly.
var childNode = node as IChildNode;
if( !object.ReferenceEquals( childNode, null ) )
return childNode.Parent;
// Otherwise, fall back on a default implementation.
return FindParent( node, node.Root );
}
}
Run Code Online (Sandbox Code Playgroud)
现在,新库的所有用户都可以完全相同地处理传统和现代实现.
重载.扩展方法可能有用的另一个领域是为接口方法提供重载.您可能有一个方法具有多个参数来控制其操作,其中只有前一个或两个在90%的情况下很重要.由于C#不允许为参数设置默认值,因此用户每次都必须调用完全参数化的方法,或者每个实现必须实现核心方法的重要过载.
相反,扩展方法可用于提供简单的重载实现:
public interface ILongMethod {
public bool LongMethod( string s, double d, int i, object o, ... );
}
...
public static LongMethodExtensions {
public bool LongMethod( this ILongMethod lm, string s, double d ) {
lm.LongMethod( s, d, 0, null );
}
...
}
Run Code Online (Sandbox Code Playgroud)
请注意,这两种情况都是根据接口提供的操作编写的,并且涉及琐碎或众所周知的默认实现.也就是说,你只能从一个类继承一次,并且有针对性地使用扩展方法可以提供一种有价值的方法来处理接口缺少的基类提供的一些细节:)
编辑: Joe Duffy的相关帖子:扩展方法作为默认接口方法实现