Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restrict generic extension method from extending strings

I have a very generic extension method to show any type of list within a console:

public static void ShowList<T>(this IEnumerable<T> Values)
{
    foreach (T item in Values)
    {
        Console.WriteLine(item);
    }
}

Not when I have a string I can use this Method

string text = "test";
text.ShowList();

But in case of string it doesn't make sense in my application.

How can I exclude string from this method? I've read something about

ShowList<T>(this IEnumerable<T> Values): Where != string //doesn't work
like image 246
Toshi Avatar asked Dec 02 '16 09:12

Toshi


People also ask

Can extension methods be private?

Extension methods can't access the private/protected methods in the extended type; it prompts you an error related to protection level. The concept of extension methods cannot be applied to fields, properties or events.

Can we override extension method?

You can use extension methods to extend a class or interface, but not to override them. An extension method with the same name and signature as an interface or class method will never be called.

Are extension methods good practice?

For an application programmer, extension methods are an incredibly powerful and expressive tool. They enable convenience, extensibility, and an improved intellisence experience. However, many of the features that make extension methods so useful for library consumers can be problematic for class library authors.

How can the ambiguous extension method be resolved?

Ambiguity can be resolved if concurrent namespaces which have extension methods with same name, are included at different levels (most inner included namespace will have priority).


2 Answers

You can create another overload of ShowList() that is specific for string and mark it as [Obsolete]:

[Obsolete("Not intended for strings", true)]
public static void ShowList(this string val)
{
}

By passing true to the IsError parameter, the compiler will prevent you from using the method.

See ObsoleteAttribute

like image 27
haim770 Avatar answered Oct 10 '22 01:10

haim770


This feels like a bit of an odd requirement to start with, to be honest - if something should work for any sequence of characters, then it should work for a string, which is a sequence of characters.

If you really want to make it fail to compile, you could add an overload accepting string which is marked as obsolete:

[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete(IsError = true, Message = "A string is a sequence of characters, but is not intended to be shown as a list")]
public static void ShowList(this string text)
{
    throw new NotSupportedException();
}

Overload resolution will pick that method, and then it'll fail to compile. The EditorBrowsable attribute will hopefully remove this from Intellisense - but you'll have to see whether that actually works. (It may show the other overload still, even though that wouldn't be picked.)

Another option would be to implement ShowList<T> as if the string was a single-entry list:

// Specialization to avoid listing each character separately.
public static void ShowList(this string text) => new[] { text }.ShowList();

In other words, make it valid to call, but handle it more appropriately.

like image 170
Jon Skeet Avatar answered Oct 10 '22 01:10

Jon Skeet