.NET Добавление диапазона символов в список

2

Я хотел бы спросить, есть ли более элегантный способ сделать это:

List<char> unallowed = new List<char>();

for (char c = '\u0000'; c <= '\u0008'; c++) {
    unallowed.Add(c);
}

for (char c = '\u000B'; c <= '\u000C'; c++) {
    unallowed.Add(c);
}

// And so on...

Мне нужно добавить в список несколько смежных диапазонов символов Юникода, и единственное, что я могу придумать для рефакторинга вышеприведенного кода, - это создать мой собственный метод, чтобы избежать повторного набора циклов for. И я даже не уверен, что это того стоит.

  • 0
    Возможно, ваш подход плох для проблемы, которую вы пытаетесь решить. Например, может быть проще использовать регулярное выражение для сопоставления или проверить каждый символ на Char.IsControl (). Что именно вы пытаетесь сделать?
  • 0
    ответил на комментарий
Теги:
list
refactoring

6 ответов

4
Лучший ответ

Хорошо, вы могли бы сделать что-то вроде:

    List<char> chars = new List<char>();
    chars.AddRange(Enumerable.Range(0x0000, 9).Select(i => (char)i));
    chars.AddRange(Enumerable.Range(0x000B, 2).Select(i => (char)i));

Не уверен, что это того стоит, тем не менее - особенно с учетом необходимости использовать "счет", а не "конец". Вероятно, проще написать собственный метод расширения...

static void AddRange(this IList<char> list, char start, char end) {
    for (char c = start; c <= end; c++) {
        list.Add(c);
    }
}
static void Main() {
    List<char> chars = new List<char>();
    chars.AddRange('\u0000', '\u0008');
    chars.AddRange('\u000B', '\u000C');
}

Повторите свой комментарий; методы расширения не являются функцией .NET 3.5. Это функция С# 3.0. До тех пор, пока вы скомпилируете набор кодов для установки .NET 2.0/3.0 (в зависимости от ситуации), не имеет значения, не имеет ли клиент .NET 3.5; вам, однако, нужно определить ExtensionAttribute - несколько строк кода:

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Assembly |
        AttributeTargets.Class | AttributeTargets.Method)]
    public sealed class ExtensionAttribute : Attribute { }
}

Или просто пойдите для взлома и загрузите LINQBridge и используйте все LINQ-to-Objects в .NET 2.0.

  • 0
    @Marc: Хорошая альтернатива. Просто хочу отметить, что это особенность .Net 3.5. Лично для меня это не очень хороший выбор, так как многие из моих приложений должны работать в средах (обычно больших, корпоративных), где 3.5 не всегда распространен, и запрос на обновление может быть затруднен.
  • 0
    «Просто хочу указать, что это особенность .Net 3.5» - нет, это не так; смотрите обновление.
1

Добавление метода добавления диапазона, вероятно, является самым простым рефакторингом, и я думаю, что это того стоит, просто потому, что он упрощает чтение диапазонов. Используя MiscUtil Range класс, вы можете сделать что-то вроде:

list.AddRange('\u000b'.To('\u000c').Step(1))

но это было бы еще менее понятно, чем наличие дополнительного метода (возможно, метода расширения на List<char>?) и записи:

list.AddCharRange('\u000b', '\u000c');

Дополнительный рывок в порядке для одного или двух вызовов, но если вы повторяете это несколько раз, вы действительно хотите избавиться от как можно большего количества постороннего текста, чтобы выделить полезные данные. Стыдно, что методы расширения не рассматриваются инициализаторами коллекции, так как в противном случае было бы очень аккуратное решение.

Вам определенно нужен List<char>, хотя из-за других ограничений? Это похоже на то, что вы действительно хотите, чтобы Predicate<char> говорил, разрешен ли символ, и который может быть реализован путем объединения диапазонов и т.д.

0

Было бы разумно иметь запрещенные символы Unicode в списке, который вы читаете из файла или внутреннего ресурса, а не жестко закодированы в приложении.

  • 0
    В .NET тип данных char - это 16-битный символ Unicode.
  • 0
    Нет, символ C # содержит символы Unicode. (хотя не уверен, как он обрабатывает суррогаты и другие> 2-байтовые символы)
Показать ещё 3 комментария
0

Вы можете поместить диапазоны в массив и выполнить цикл:

char[] ranges = {
   '\u0000','\u0008',
   '\u000b','\u000c',
   '0','9',
   'a','z'
};

for (int i = 0; i < ranges.Length; i++) {
   for (char c = ranges[i++]; c <= ranges[i]; c++) {
      unallowed.Add(c);
   }
}
0

Это в значительной степени, как я создаю списки Char (на самом деле это произошло только вчера). Если у вас есть много диапазонов для добавления в список, вы можете сделать его немного проще/менее повторяющимся, указав такой метод, как AddUnallowed (char from, Char to), который добавляется в список.

0

В вашем коде есть несколько дубликатов, как вы уже узнали. И дублирование обычно плохое, и метод сделает ваш код более читабельным, поэтому он считает, что это того стоит. Как насчет метода расширения:

public static class YourHelper
{
    public static void AddCharRange(this List<char> list, char first, char last)
    {
        for (char c = first; c <= last; c++)
        {
            list.Add(c);
        }
    }
}

а затем:

List<char> unallowed = new List<char>();
unallowed.AddCharRange('\u0000', '\u0008');

В зависимости от вашего варианта использования, я бы назвал метод "Unallow" вместо "AddCharRange".

Ещё вопросы

Сообщество Overcoder
Наверх
Меню