Подтвердить что ты не робот

Ограничить общий метод расширения от продолжения строк

У меня есть очень общий метод расширения для отображения любого типа списка в консоли:

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

Нет, если у меня есть string, я могу использовать этот метод

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

Но в случае string это не имеет смысла в моем приложении.

Как я могу исключить string из этого метода? Я кое-что прочитал о

ShowList<T>(this IEnumerable<T> Values): Where != string //doesn't work
4b9b3361

Ответ 1

Это кажется немного странным требованием для начала, если честно - если что-то должно работать для любой последовательности символов, тогда оно должно работать для строки, которая представляет собой последовательность символов.

Если вы действительно хотите, чтобы это не удалось скомпилировать, вы могли бы добавить прием перегрузки string, который помечен как устаревший:

[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();
}

Разрешение перегрузки выберет этот метод, а затем он не сможет скомпилироваться. Атрибут EditorBrowsable, надеюсь, удалит это из Intellisense, но вам нужно будет увидеть, действительно ли это работает. (Это может показать еще одну перегрузку, даже если это не будет выбрано.)

Другим вариантом было бы реализовать ShowList<T>, как если бы строка была списком с одним входом:

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

Другими словами, сделайте его действительным для вызова, но обработайте его более соответствующим образом.

Ответ 2

Вы можете создать еще одну перегрузку ShowList(), которая имеет значение для string и пометить ее как [Obsolete]:

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

Передавая true параметру IsError, компилятор помешает вам использовать этот метод.

См. ObsoleteAttribute

Ответ 3

Для молчащего игнорирования вы можете использовать это:

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

Или, если вы хотите также написать строку:

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);
        }
}