Move all extension methods into separate namespace(s)
When writing code that uses ServiceStack, its fairly common to import the ServiceStack namespace (or others) via a using statement. Doing so will make all the extension methods within that namespace available.
I have experienced several cases where I have my own custom extension methods with a conflicting signature that I would like to use instead of the ServiceStack method. However there is no ideal way to disambiguate them currently. My only choices are:
1) Move code around into separate files so that I only import either the ServiceStack namespace or my namespace.
2) Refer to the proper method by including the name of the static class, and not using the extension method syntax.
Example:
var message = "Hello, {0}".FormatWith("World");
would become:
var message = MyCustomNamespace.StringExtensions.FormatWith("Hello, {0}", "World");
My suggestion is to move all your extension methods into separate namespaces that follows a consistent pattern.
If they are in "ServiceStack" they are now found in "ServiceStack.Extended". Or if "ServiceStack.Text" then "SericeStack.Text.Extended", etc. I'm not suggesting moving them to a separate dll.
Thanks,
Casey
References:
"The call is ambiguous"
https://stackoverflow.com/questions/5283583/extension-methods-conflict
"Put extension methods into their own namespace"
https://blogs.msdn.microsoft.com/vbteam/2007/03/10/extension-methods-best-practices-extension-methods-part-6/

That’s the opposite of how ServiceStack is designed, hurts discoverability, increases the friction and support burden due to broken references and would result in unacceptable breaking changes. The only extension methods we plan on removing are those duplicated by newer versions of the .NET Framework.
-
Generally we're strongly against making breaking changes to existing methods but as the To<T> extension methods aren't documented and the preferred APIs is to use AutoMapping Utils ConvertTo<T> methods instead I've moved them to ServiceStack.Text namespace (and deprecated them) which reduces the potential breaking change whilst allowing IDE's like Rider/ReSharper to still be able to find them.
This change is available in v5.2.1 that's now available on MyGet:
http://docs.servicestack.net/myget -
Connor O'Shea commented
Demis, I hope you'll reconsider part of this. I'm all for extension methods for types that ServiceStack owns and for types that provide a much nicer dev experience like the HTTP Utils you mention. However, it drives me nuts that you've made certain public extension methods available in the base ServiceStack namespace for types that you don't own, like string.
For example, in almost every one of my projects I run into the following conflict. ServiceStack defines `public static T To<T>(this string value)` in StringExtensions.cs. I have my own internal library that has many other extension methods that defines `public static T To<T>(this IConvertible obj)`. Half the time the code won't compile because the method call is ambiguous. The other half it's picking your method over mine and throwing an exception at runtime since ServiceStack's intent is to deserialize while my intent is to call Convert.ChangeType under the hood.
-
Casey commented
Demis,
Thank you very much for taking the time to explain this to me. It helps to see the history, and to know that you've tried this already, and have given it a great deal of thought.
As a bit of context, I use ReSharper and I never have any problems finding extension methods, but I could see that being a problem for those who don't.
Extension methods are probably my favorite language feature of C#, and I certainly appreciate the development experience with them.
I am complete on this topic. Thank you.
-
We used to hide extension methods behind custom namespaces in v3, it created a terrible dev experience, with frequent reported issues on not from being able to find API, broken refs, bloated namespaces, etc.
HTTP Utils and OrmLite are examples of extension methods on built-in APIs which provide a much nicer dev experience because their extension methods on built-in types, it enables a cleaner, leaner, more readable/reusable/composable functionality with minimal abstraction/dependencies, etc. These APIs would be nowhere near as pleasant to use if they were tacked on an artificial abstraction instead. ServiceStack leverages the utility of extension methods pervasively throughout out its code-base because of these attributes.
We've already experienced the ugliness of hiding extension methods in custom namespaces, v3 code base is more verbose and had poorer discoverability as a result. Whilst we're careful about which extension methods we add on string/object/etc, we add them when APIs are generic and useful. When it makes sense to we'll add them on a custom namespace so they light up when you're working in that domain, e.g. ServiceStack.OrmLite, ServiceStack.IO but otherwise general purpose utils belong in the base ServiceStack namespace where they can be found.
Extension methods are one of C#'s greatest language features to enable a simpler, leaner, more readable and productive dev UX. We use them extensively when they add value or when we believe .NET has missing APIs on their built-in types. Our approach continues to serve us well and has had very few complaints because of this (I can't remember the last time this was reported as an issue).
Unfortunately .Fmt() and FormatWith() were added to make up for the lack of string interpolation in C#, they wouldn't exist if C# had implemented it much earlier. I may consider moving FormatWith() in a ServiceStack.Legacy namespace in v5.
-
Casey commented
I understand about the breaking changes.
For any new work, where your time and energy are already being spent on a new direction..., I'm hoping you consider this concern for extension methods on types that you don't own, such as System.String.
Thanks.