Toshi
Toshi

Reputation: 2608

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

Upvotes: 18

Views: 1031

Answers (3)

Jon Skeet
Jon Skeet

Reputation: 1504182

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.

Upvotes: 31

haim770
haim770

Reputation: 49123

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

Upvotes: 9

Peter B
Peter B

Reputation: 24280

For silent ignore you could use this:

public static void ShowList<T>(this IEnumerable<T> Values)
{
    if (Values is String) return;
    // ...
}

Or if you want to also write the string:

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

Upvotes: 3

Related Questions