मुझे लगता है कि विस्तार विधियों के न्यायसंगत उपयोग ने (सार) आधार वर्गों के साथ एक और अधिक समेकित स्थिति पर इंटरफेस लगाए।
Versioning. One advantage base classes have over interfaces is that you can easily add new virtual members in a later version, whereas adding members to an interface will break implementers built against the old version of the library. Instead, a new version of the interface with the new members needs to be created, and the library will have to work around or limit access to legacy objects only implementing the original interface.
एक ठोस उदाहरण के रूप में, लाइब्रेरी का पहला संस्करण इस प्रकार एक इंटरफ़ेस परिभाषित कर सकता है:
public interface INode {
INode Root { get; }
List GetChildren( );
}
पुस्तकालय जारी होने के बाद, हम मौजूदा उपयोगकर्ताओं को तोड़ने के बिना इंटरफ़ेस को संशोधित नहीं कर सकते हैं। इसके बजाय, अगली रिलीज में हमें अतिरिक्त कार्यक्षमता जोड़ने के लिए एक नया इंटरफ़ेस परिभाषित करने की आवश्यकता होगी:
public interface IChildNode : INode {
INode Parent { get; }
}
हालांकि, नई लाइब्रेरी के उपयोगकर्ता केवल नए इंटरफ़ेस को लागू करने में सक्षम होंगे। विरासत कोड के साथ काम करने के लिए, हमें पुराने कार्यान्वयन को अनुकूलित करने की आवश्यकता है, जो एक विस्तार विधि अच्छी तरह से संभाल सकता है:
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 );
}
}
अब नई पुस्तकालय के सभी उपयोगकर्ता विरासत और आधुनिक कार्यान्वयन दोनों को समान रूप से इलाज कर सकते हैं।
Overloads. Another area where extension methods can be useful is in providing overloads for interface methods. You might have a method with several parameters to control its action, of which only the first one or two are important in the 90% case. Since C# does not allow setting default values for parameters, users either have to call the fully parameterized method every time, or every implementation must implement the trivial overloads for the core method.
इसके बजाय विस्तार विधियों का उपयोग छोटे अधिभार कार्यान्वयन प्रदान करने के लिए किया जा सकता है:
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 );
}
...
}
Please note that both of these cases are written in terms of the operations provided by the interfaces, and involve trivial or well-known default implementations. That said, you can only inherit from a class once, and the targeted use of extension methods can provide a valuable way to deal with some of the niceties provided by base classes that interfaces lack :)
Edit: A related post by Joe Duffy: Extension methods as default interface method implementations