C # Операторы и удобочитаемость - PullRequest
5 голосов
/ 24 октября 2009

Я просто работал над кодом и поймал себя на том, что делаю эту ошибку

if (stringName == "firstName" || "lastName")
   // Do code 

очевидно, что это неправильно и должно быть

if (stringName == "firstName" || stringName == "lastName")
   // Do code 

но это только заставило меня задуматься относительно читабельности, будет ли легче первое? Может быть, с некоторой логикой, которая могла бы сказать, если не указано новое stringName, используйте первое?

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

Ответы [ 10 ]

11 голосов
/ 24 октября 2009

Я думаю, что ваше предложение нарушит правила синтаксического разбора выражений - теперь символ '==' становится оператором квадренирования (?), А не двоичным. Однако я обнаружил, что пропускаю оператор SQL IN и использовал что-то вроде этого:

if (stringName.In("foo", "bar", "baz"))
{

}

// in an extension method class
public static bool In<T>(this T value, params T[] values)
{
    return values.Contains(value);
}
10 голосов
/ 24 октября 2009

Проблема в том, что если работает на логических значениях.

stringName == "firstName" возвращает логическое значение.
"lastName" является строковым литералом.

|| - это логическое значение или оператор с коротким замыканием, которое принимает логические значения с обеих сторон.

Другими словами, вы хотите изменить определение ||, что обычно является плохой идеей.

Теоретически, вы можете сделать так, чтобы синтаксический анализатор понял, что вы имеете в виду ... но это очень быстро становится двусмысленным.

if (stringName == firstName || lastName)

Выглядит хорошо, верно? Но что именно фамилия?

Что если я это сделаю?

const bool lastName = false;

Кроме того, && является противоположностью ||, но stringName == firstName && lastName не является противоположностью вышеуказанной логики и фактически не имеет смысла.

6 голосов
/ 24 октября 2009

То, что компилятор догадывается о намерениях программиста, когда код явно неверен, чтобы исправить это, действительно очень плохая идея.

2 голосов
/ 24 октября 2009

Даже с круглыми скобками это не имеет смысла. stringName == ("firstName" || "lastName") похоже, что вы хотите проверить истинность двух строк, и эти строки всегда будут истинными, а затем сравнить этот логический результат со строкой stringName.

Если вы добавите круглые скобки, как это (stringName == "firstName") || "lastName", условие также всегда будет истинным, поскольку "lastName" всегда верно, независимо от того, равно ли stringName "firstName".

Мне нравится, как это делает Ruby:

["firstName", "lastName"].include? stringName

Вы всегда можете использовать Contains, как предлагали другие, или написать метод расширения String, где вы могли бы сделать:

stringName.EqualsOneOf(new[] {"firstName", "lastName"})
1 голос
/ 24 октября 2009

Я не возражаю против синтаксиса, подобного SQL:

if(stringName in ("firsName", "lastName"))
{
}
1 голос
/ 24 октября 2009

Я считаю, что функция Contains () решает эту проблему, то есть:

string[] ValidNames = new string[] { "firstName", "lastName"};

if(ValidNames.Contains(stringName))
{
    //Do Code
}
1 голос
/ 24 октября 2009

Это сработало бы, только если operator||(string,string) вернуло ... своего рода набор строк, и у вас была перегрузка Equals, которая приняла строку и этот набор строк и проверила, что строка находится в коллекции. Похоже, большая работа была проделана за кулисами для очень редко используемой конструкции.

Тем более, что вы уже можете сделать что-то вроде:

if(new string[]{"firstName","lastName"}.Contains(stringName))
    // code
1 голос
/ 24 октября 2009

Причина, по которой они не допустили такой синтаксис, была, скорее всего, из-за читабельности. Если вы просматриваете код в первый раз и не совсем в своем лучшем состоянии, вы можете не сразу увидеть, что сравниваете stringName с "firstName" и "lastName". Это просто делает ваши намерения намного более определенными.

Опять же, скобки могут решить эту проблему.

0 голосов
/ 24 октября 2009

Когда FCL содержит множество возможностей для создания самых разнообразных ответов, представленных в этом потоке, вам не нужно иметь более гибкий синтаксис C #, потому что читаемость вскоре становится особенностью того, как вы создаете ответ среди всего множества. Он сводится к выбору между вызовами метода и объекта большую часть времени.

Вот пример (просто еще один из многих) того, как можно найти одну или несколько строк одновременно в массиве строк или применить любые другие критерии, которые вы считаете подходящими для этого набора строк. Отступы, пробелы и комментарии к коду играют большую роль для понимания этого примера кода, как и для любого кода.

        bool found = Array.Exists(
            // array of strings to search
            new[] { "c#", ".net", "programming", "design patterns", "work", "play", "bits", "bytes", "break" },
            // criteria - can even satisfy multiple conditions simultaneously if desired
            str => (str == ".NET" || str == "work") //look for ".NET" or "work"
            );
0 голосов
/ 24 октября 2009

Вот почему я всегда по привычке:

if ((stringName == "firstName") || (stringName == "lastName"))
   // Do code

Через некоторое время это становится второй натурой.

...