У вас есть слепое пятно в программировании?
Я имею в виду, есть ли общая техника или языковая функция, к которой вы не можете привыкнуть.
Ну, у меня есть один (или, возможно, более одного), и мое использование delegate
.
Руки вверх! Кто еще не чувствует себя комфортно с делегатами? Будьте честны!
Так, что делегат?
Поскольку мои курсы в университете познакомили меня с Си, я знаю о функциональных указателях.
Указатели на функции удобны, если вы хотите передать методы в качестве аргументов.
На мой взгляд, делегат - это что-то вроде указателя на функцию. Эврика! Я понял. У меня нет!
Конкретный сценарий?
Я хотел бы удалить любую строку из текстового файла, которая соответствует регулярному выражению .
Предполагая, что у меня есть коллекция строк, List<T>
имеет метод RemoveAll
, который, кажется, идеально подходит для этой цели.
RemoveAll
ожидает метод оценки в качестве аргумента для принятия решения о том, удалять или оставлять элемент списка.
И вот оно: указатель на функцию!
Любой код здесь?
public static int RemoveLinesFromFile(string path, string pattern)
{
List<string> lines = new List<string>(File.ReadAllLines(path));
int result = lines.RemoveAll(DoesLineMatch);
File.WriteAllLines(path, lines.ToArray());
return result;
}
Итак, я ищу функцию DoesLineMatch
, которая оценивает, соответствует ли линия шаблону.
Вы видите проблему?
RemoveAll
ожидает делегата Predicate<string> match
в качестве аргумента.
Я бы закодировал это так:
private static bool DoesLineMatch(string line, string pattern)
{
return Regex.IsMatch(line, pattern);
}
Но тогда я получаю сообщение об ошибке «Ожидается метод с подписью« bool DoesLineMatch (string) »».
Что мне здесь не хватает?
Это работает вообще?
Вот как я наконец заработал:
public static int RemoveLinesFromFile(string path, string pattern)
{
List<string> lines = new List<string>(File.ReadAllLines(path));
int result = lines.RemoveAll(delegate(string line)
{
return Regex.IsMatch(line, pattern);
});
File.WriteAllLines(path, lines.ToArray());
return result;
}
Я счастлив, что это работает, но я не понимаю этого.
А в чем вопрос?
То, что я сделал, чтобы заставить его работать, это просто использование метода.
Насколько я понимаю, это просто некий код «один раз и уничтожь».
Если вы используете переменную или метод только один раз, вы можете встроить их, но встраивание всегда эквивалентно объявлению в явном виде.
Есть ли способ объявить метод явно? Как бы я это сделал?
PS: простите, что мой вопрос несколько длинен.
PPS .: Как только я получу эту делегатскую вещь, я сделаю скачок с 2,0 до 3,0 и изучу лямбды.
PPPS .: Следуя Намек Джона на эффективность Regex.IsMatch(string, string)
Я изменил свой код:
int result = lines.RemoveAll(delegate(string line)
{
Regex regex = new Regex(pattern);
return regex.IsMatch(line);
});
Это не сильно помогает в вопросах эффективности. Поэтому я последовал предложению ReSharper и переместил реализацию Regex во внешнюю область:
Regex regex = new Regex(pattern);
int result = lines.RemoveAll(delegate(string line)
{
return regex.IsMatch(line);
});
Теперь ReSharper убедил меня заменить это группой методов:
Regex regex = new Regex(pattern);
int result = lines.RemoveAll(regex.IsMatch);
И это очень похоже на ответы, предложенные здесь. Не то, что я просил, но опять же я поражен, как ReSharper (и, конечно, Stack Overflow) помогает учиться.