Create static extension methods for types?
I don't think this is possible, but is there a way to add a static extension method to a type? So that I can add the static DoSomething() to class Widget? This would be very helpful for me, but I have seen no examples of it yet.
Thanks
Answers
Well, the problem is that extension methods are static methods, the first parameter of method is the instance of the type you want the method to apply to.
I can see what you're asking; but what would be the benefit of that? If I could add that sort of method to Widget, it would be called as:
Code SnippetWidget.DoSomething()
What feature does that add? It does nothing with an Widget instance...
All Replies
Well, the problem is that extension methods are static methods, the first parameter of method is the instance of the type you want the method to apply to.
I can see what you're asking; but what would be the benefit of that? If I could add that sort of method to Widget, it would be called as:
Code SnippetWidget.DoSomething()
What feature does that add? It does nothing with an Widget instance...This would be useful since I'd like to use it on some third party libraries that I have. For example, one library lets me add a "Category" to an object with the category class. The library already has a static Category.Lookup(...) method. I'd like to add a static Category.LookupOrCreate(...) method to the Category type. So it's just for convenience, but it would be cleaner to do this rather than make a CategoryUtilities class, which I have now.
I don't really see what the convenience is. With extension methods you extend instances because they have data you can do something with. For example, in C# 2.0 you could do something like this:
Code Snippetinternal static class Utility {
public static int WordCount(String text) { /* ... */ }
}
and use it as:
Code SnippetString text = "the fox jumped over...";
int wordCount = Uility.WordCount(text);
That WordCount method in C# 3.0 can be slightly changed to this:
Code Snippetinternal static class Utility {
public static int WordCount(this String text) { /* ... */ }
}
.. to become an extension method which can then be used like this:.
Code SnippetString text = "the fox jumped over...";
int wordCount = text.WordCount();
The convenience here is that's more clear that you doing something on the text object and don't have to be concerned about the Utility static class anymore. There's really no convenience to have an extension method on a static class because there's no instance to operate on. In C# 2.0 you could never write a method to do "Utility.LookUpOrCreate(Category);" because there's no instance of anything to use. You'd go from "Utility.LookUpOrCreate(...)" to "Category.LookUpOrCreate(...)". I don't see the value in doing what you're asking. Just because LookUp is a static method of Category doesn't mean it has anything to do with Category. With an extension method like int WordCount(this String text) you know you have something to do with a String object.
The other problem is how do you declare such a method. With current extension methods it's easy, you've got an instance parameter you need to do anything with an instance of the type in question, so they reused the this keyword on that parameter to denote it as being an extension method. Without the ability to create an instance of a static class (and therefore be used as a parameter), how can you associate that method with that static class? You can't do:
Code Snippetstatic void LookupOrCreate(this Category category) {/*...*/}...because Category can't be passed as an object.
I should have been a bit clearer. In my example I am faced with a class that looks like this (that I can't change):
Code Snippetpublic class Category
{
public static Category LookupCategory(...) {}
public static Category Create(...){}
}
I'd like to add some extra methods such as the public static Category LookupOrCreateCategory(...) method I mentioned earlier.
Obviously the LookupOrCreateCategory method wouldn't have access to any of the internals of the actual Category class, but it would still be nice from an organizational point of view.
You could have:
Code Snippetnamespace CategoryExtensions
{
internal static class Extensions
{
public static Category LookupOrCreate(this Category that) { return new Category();}
}
}
which could be called as:
Code SnippetCategory category = new Category();
category = category.LookupOrCreate();
Since you need an instance to associate with the extension method, you needlessly have to create a temporary Category object just to get that association between the extension method and Category. It would be much clearer as:
Code SnippetCategory category = Utility.LookupOrCreate(...);
Without that instance there's no reliable way to associate an extension method with a type. e.g:
Code Snippetpublic static Category LookupOrCreate(...) {/* ... */}
... how could you change that declaration without adding a new keyword and without breaking existing code that could associate that method with the type Category?
You could subclass Category and add your own. Then, you can "override" references to Category with your own with "using Category = MyOwnNamespace.MyCategory". Depending on what you're doing, this could screw things up. For example, if you expose your category outside of your own code, other people could accidentally start using your version. Some automatic serialization, etc. might also get tinkered with. But if this is just pure consumption in your own assembly, you might not run into many issues.
Extension methods aren't really for this. They are just simple (or shortsighted depending on your view) ways to get infix semantics.
-MichaelIf I could add my point of view:
I think there is no reason to extend 3rd party library integrating our static methods into other libraries.
For code maintenance is better to have own static class with static methods in own namespace which add new functionality to any library.
If you have source code of library you can add to it your files and use partial classes to add new functionality to existing classes.
Ie:
Code Snippet//file1.cs
namespace MyCompany.Utilities
{
public class Widget
{
public static void DoSomething()
{
}
}
}
//file2.cs
using 3rdParty.Utilities;
using MyCompany.Utilities;
namespace MyCompany.Project1
{
public class App
{
..
public void Foo()
{
Widget.Do3rdPartyMethod()
Widget.DoSometing(); //you run your method
}
}
}
- That would give you an ambiguous reference error C0104.
Dariusz Jankowski wrote: If I could add my point of view:
I think there is no reason to extend 3rd party library integrating our static methods into other libraries.
For code maintenance is better to have own static class with static methods in own namespace which add new functionality to any library.
If you have source code of library you can add to it your files and use partial classes to add new functionality to existing classes.
Ie:
Code Snippet//file1.cs
namespace MyCompany.Utilities
{
public class Widget
{
public static void DoSomething()
{
}
}
}
//file2.cs
using 3rdParty.Utilities;
using MyCompany.Utilities;
namespace MyCompany.Project1
{
public class App
{
..
public void Foo()
{
Widget.Do3rdPartyMethod()
Widget.DoSometing(); //you run your method
}
}
}
Yes, You are right, Peter. I forgot it, and didn't test code.
So, the code should be changed to:
Code Snippet//file1.cs
namespace MyCompany.Utilities
{
public class Widget
{
public static void DoSomething()
{
}
}
}
//file2.cs
namespace MyCompany.Project1
{
public class App
{
public void Foo()
{
3rdParty.Utilities.Widget.Do3rdPartyMethod()
MyCompany.Utilities.Widget.DoSometing(); //you run your method
}
}
}
In this case need change all references to Widget class to full qualified.
But I think You could think about another solution.
get file1.cs from previous example and add:
Code Snippet//file2_my.cs
using MyCompany.Utilities;
namespace MyCompany.Project1
{
public partial class App
{
public void Foo1()
{
Widget.DoSometing(); //you run your method
//if you need run 3rdparty method, you run boxed method
this.Foo2();
//or run by fully qualified name
3rdParty.Utilities.Widget.Do3rdPartyMethod();
}
}
}
//file2_3rd.cs
using 3rdParty.Utilities;
namespace MyCompany.Project1
{
public partial class App
{
public void Foo2()
{
Widget.Do3rdPartyMethod()
}
}
}
Think about Windows API and .NET.
.NET is "packing" Windows API classes into .NET classes. This is popular method. It also simplify process of future adding new library. In your boxing methods You change only refernece to new library, you also are able to use 2 or more 3rdParty libraries, but your business rules are not changed. Your boxing method is like using interfaces in classes.
- What's the point of creating another Widget class if that forces one access to Widget to be access through the fully-qualified name?
Dariusz Jankowski wrote: Yes, You are right, Peter. I forgot it, and didn't test code.
So, the code should be changed to:
Code Snippet//file1.cs
namespace MyCompany.Utilities
{
public class Widget
{
public static void DoSomething()
{
}
}
}
//file2.cs
namespace MyCompany.Project1
{
public class App
{
public void Foo()
{
3rdParty.Utilities.Widget.Do3rdPartyMethod()
MyCompany.Utilities.Widget.DoSometing(); //you run your method
}
}
}
In this case need change all references to Widget class to full qualified.
But I think You could think about another solution.
get file1.cs from previous example and add:
Code Snippet//file2_my.cs
using MyCompany.Utilities;
namespace MyCompany.Project1
{
public partial class App
{
public void Foo1()
{
Widget.DoSometing(); //you run your method
//if you need run 3rdparty method, you run boxed method
this.Foo2();
//or run by fully qualified name
3rdParty.Utilities.Widget.Do3rdPartyMethod();
}
}
}
//file2_3rd.cs
using 3rdParty.Utilities;
namespace MyCompany.Project1
{
public partial class App
{
public void Foo2()
{
Widget.Do3rdPartyMethod()
}
}
}
Think about Windows API and .NET.
.NET is "packing" Windows API classes into .NET classes. This is popular method. It also simplify process of future adding new library. In your boxing methods You change only refernece to new library, you also are able to use 2 or more 3rdParty libraries, but your business rules are not changed. Your boxing method is like using interfaces in classes.
I think I didn't clearly described code in example.
In file2_my.cs you try to write methods which should use owned static methods from MyCompany.Utilities.Widget class (I tried to simulate problem so I used the same name of class. In the future you could order such class in some company which will write code simpler and code will be faster or someting else)
If in this class you really need invoke method from 3rdParty library, you do it by boxing (you can create method with several different parameters, and in boxing method do some processing and invoke proper methods in 3rd party library) or use fully qualified name.
I think this is long way, but if you really need and you don't have ability to change 3rd party code maybe this is solution.
If not, Peter gave good examples: use extension methods or some static classes.
You decide how you code will be changed in the future and how you would like to manage it.
I don't know your business rules so decision is your.
If it is not helpful, please forgot it.
I think that would be a useful feature, but I don't see it being added to VS Orcas. If you submit a suggestion to connect.Microsoft.com, I'll vote for it.
Jonathan
- I would vote for it too!
I think it's really much cleaner than 10 people having 10 different libraries with 10 different names.
Whereas this way, a team could have standard extension methods that they all agree when adding new methods.
IMO it's the same excuse coming from people saying (from Ian Suttle's blog):
"These are types I just don’t want to derive from and modify – I prefer the built-in ease of use. I’ve longed for a method on a checkbox list which returns a collection of items which were checked. Instead we must loop through the checkbox list and build our own collection. An extension method can resolve this issue for us without creating a completely new asp.net user control."
That's the same reason we need static extension methods (need a better wording).
Thanks,
Aw - Peter,I can't tell why you're discounting the idea. I mean, do you not understand the use case or are you being defensive? There are several reasons to add extension methods to a static class. An extension method has nothing to do with instances of objects per se. It's just a way to extend the functionality of a class. Static classes are just like instance classes insofar as their functionality isn't always adequate. For example, what would be wrong with adding an IsEmpty method to the string class? To me, it makes a lot more sense to have a call like string.IsEmpty() that parallels string.IsNullOrEmpty() rather than string.IsNullOrEmpty() and "foo".IsEmpty().Patrick
I must say that I really think extension properties and static extension methods must be added.
Why use an static extension method?
For the same reason we use an extension method for an instance.
I could call:
StringUtils.CountWords(someString) or I could call someString.CountWords().
The second option is only easier to use. This is not doing anything else than simplifying my life, as I write: somestring. and the CountWords method is there.So, if I am working with 3rd party class, I would really like to do:
int. and see that there is a NullableParse method. Today, I have a NullableParser class, that has:
ParseInt32 (the method returns a Nullable<Int32> value if the value is null, still throws an exception if the value is invalid, and returns the right value if possible).
ParseInt16
ParseByte and so on.
If I could add NullableParse to Int32, I would do it. It will be a lot easier, specially for other developers in my team to simple use:
int. and see a new method there.
Paulo Zemek - System Architect- The DateTime class has static methods .MinValue and .MaxValue which I find very useful. Unfortunately, these values are invalid in SQL Server. I would like to be able to add methods .SQLMinValue (isSmall) and .SQLMaxValue(isSmall) to return the appropriate datetime and smalldatetime values.
Sure I can do this in a separate class, like MyPersonalUtilityClass, or some other class where my methods will fall by the wayside, be forgotten, and then rewritten. Or I could make it a static method in the DateTime class, and have it always be close to hand. It's a lot easier to always include a reference to a helper namespace, and have my helper methods appear in the context in which they are useful, than to remember each and every method and where to find it. - I found this thread because I, too, want to have this feature. I'm working on a project that has a bunch of layers, including a Model layer. The Web layer (front-end) needs to create a new instance of a Model object, so I originally did - new BusinessObject() - but I want certain properties to be initialized when a new one is being created. And I mean at a logical level, not just anytime the class is instantiated, like when LINQ to SQL is doing its thing. So I wrote this static factory method right on the model object:
public static BusinessObject New()
{
return new BusinessObject {
Prop1 = "value1",
DateCreated = DateTime.Now,
collection = new List<Whatever>()
};
}
I can call this from the Web layer to create a new logical object with all the right properties set. But now, part of this project's aim is to keep all business logic not in the Model layer but in the Service layer. So I thought "I want an extention method in the Service layer that will allow the business rules to reside there but to be accessed directly from the model type itsself. Here's my theoretical syntax:
namespace Service {
public static class ModelExtensions {
public static Model.BusinessObject Model.BusinessObject.New() {
return new Model.BusinessObject {
Prop1 = "value1",
DateCreated = DateTime.Now,
collection = new List<Whatever>()
};
}
}
}
Twould be nice.
Mark - Following syntax wouldn't need any new keywords (at least not in C#)
public class ExtensionsOnSomeType
{
// current supported syntax od regular extension methods
static void InstanceExtension(this SomeType)
{
// Do your stuff here
}
// current NOT supported syntax for static extension methods
// The static keyword before (or after) the "this" keyword would tell the compiler this is a static extension method
static void InstanceExtension(static this SomeType)
{
// Do your stuff here
}
}
Serge Desmedt - http://sdesmedt.wordpress.com - This would be an example use, with hypothetical syntax:
static public void WriteLine(this System.Diagnostics.Debug, String format, params Object[] args) { System.Diagnostics.Debug.WriteLine(String.Format(format,args)); }
- Being a linguist and a computational grammarian, I'm embarassed to admit that I didn't propose the best hypothetical syntax.
Clearly, the definite article 'the' would be a better C# keyword than the demonstrative determiner 'this':
static public void WriteLine(the System.Diagnostics.Debug, String format, params Object[] args)
{
System.Diagnostics.Debug.WriteLine(String.Format(format,args));
} - Just to add my 2 pence :)Another method that I would like to see on the int type is:public static int ParseOrDefault(string s, int defaultValue)It would simply attempt to parse a string and return the integer representation, or else return the default value if the parsing fails. This method definitely belongs on the int type imho (rather than in some helper utility type) but I can't currently extend int with a new static parse method :(Colin
I have another revival for this long thread. ConfigurationManager has properties for Microsoft's custom configuration sections, ConnectionStrings and AppSettings. I am creating a custom config section and would like to extend ConfigurationManager by adding a MySection property to return my config section in the same way. It would be great if it could be done so developers consuming my section can use it in the same way they use these Microsoft sections.
The alternatives are not so bad. I can't extend ConfigurationManager because it's sealed (I wonder how Chris Sells is doing in convincing Microsoft that classes should never be sealed) but I can wrap it or I can simply use the GetSection method. I can even create a static method in my config section handler to retrieve the section. There are a lot of good options based on many years of OOP theory. In fact, extension methods are probably the least OOP of them all but they sure are cool where they can be used and, since we have them and use them, it would be awesome if we could use them to extend a class the same way you extend an instance.- I know that this feature is not on anyone's radar, but it would be nice.
A extension to a class's static methods would be useful for this example (and the reason I want the static extension functionality)
public static class Utils { private const string SOUND_PATH = "\\Windows\\decode.wav"; public static DialogResult ShowMessageWithBeep(string message) { Beep(); return MessageBox.Show(message); } public static void Beep() { //Warning sound to get user's attention. SoundPlayer player = new SoundPlayer(SOUND_PATH); player.PlaySync(); } }If there were static extension methods then I could set this up so that when it is called it looks normal and is easily found (MessageBox.ShowMessageWithBeeb) rather then looking like a hack Utils.ShowMessageWithBeep.
As more and more methods have the useful stuff in the static methods, this feature is going to be needed. - I too would like this feature - I want to extend Math.min and Math.max to handle datetimes... That way I could easily remember where they are...
- +1
I'm looking to extend the Microsoft.VisualStudio.TestTools.UnitTesting.Assert class to add support for comparing dates to some tolerance (currently float tolerance is supported, DateTime is not). - I think the best syntax would be using a keyword that is already in the language:
public static ReturnType ExtMethod(static typeof(ExtendedType) type, object[] arguments) { return Whatever_ReturnType_Instance; }
