С# 4.0 - Как обрабатывать необязательные строковые параметры

Этот код недействителен:

private void Foo(string optionalString = string.Empty)
{
   // do foo.
}

Но этот код:

private void Foo(string optionalString = "")
{
   // do foo.
}

Почему? Поскольку string.Empty является полем readonly, а не константой, а значения по умолчанию для необязательных параметров должны быть константой времени компиляции.

Итак, на мой вопрос... (ну, беспокойство)

Это то, что я должен был сделать:

private const string emptyString = "";

private void Foo(string optionalString = emptyString)
{
   // do foo.
   if (!string.IsNullOrEmpty(optionalString))
      // etc
}

Как вы, парни, обрабатываете необязательные строковые параметры?

Почему они не могут String.Empty константу времени компиляции?

Ответы

Ответ 1

Ummm... что случилось со строкой optionalParm = "" еще раз? Почему это плохо? Вы действительно думаете, что вам нужна символическая константа для пустой строки в этом случае? Как насчет этого?

const int Zero = 0;

void SomeMethod(int optional = Zero) { }

Неужели это кажется вам глупым?

Ответ 2

если вам не нравится значение ", вы можете использовать значение по умолчанию (строка).
Я играл с ним, и это разрешено.

private static void foo(string param = default(string)) {
    if (!string.IsNullOrEmpty(param)) // or param != default(string)
        Console.WriteLine(param);
}

Ответ 3

Лучший способ справиться с ними - с помощью

private void Foo(string optionalString = "")
{
   // do foo.
}

Поэтому вы не можете использовать String.Empty. Все признают "", но если бы я нашел optionalString = nullString, я не был бы уверен, что думать. Если ничего другого, назовите вещь emptyString - это не null!

Ответ 4

Предупреждение анализа кода 1026 говорит, что не использовать необязательные параметры. Лучше использовать методы перегрузки, например:

private void Foo()
{
   Foo(string.Empty);
}
private void Foo(string optionalString)
{
   // do foo.
   if (!string.IsNullOrEmpty(optionalString))
      // etc
}

Ответ 5

Я отвечаю на этот вопрос.

Why can they not make String.Empty a compile-time constant?

Вот код дизассемблирования через Reflector of String.cs в mscorlib.dll

public static readonly Empty;
static String()
{
    Empty = "";
    WhitespaceChars = new char[] { 
        '\t', '\n', '\v', '\f', '\r', ' ', '\x0085', '\x00a0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 
        ' ', ' ', ' ', ' ', '​', '\u2028', '\u2029', ' ', ''
     };
}

Итак, в платформе windows string.Empty является именно "". Но знаете ли вы, что у марсианки есть другое определение для Empty и WhitespaceChars в их ОС.

Ответ 6

Если вы готовы проиграть и обработать нулевые символы "", а пробельные символы будут одинаковыми, вы можете по умолчанию null. Это очень удобно, когда имя пользователя и пароль являются необязательными полями из-за возможности надежного подключения к db. Вы можете изменить эту логику на строки reset на null и, таким образом, изменить assert и if. Важная часть имеет согласованное соглашение.

private void RunSql(string serverName, string databaseName, string userName = null, string password = null)
{
    userName = Strip(userName);
    password = Strip(password);

    // The `MsTest` assert - works in both `Debug` and `Release` modes.
    Assert.AreEqual<bool>(
        userName == String.Empty,
        password == String.Empty,
        "User name and password should be either both empty or both non-empty!");
   Assert.IsFalse(String.IsNullOrWhiteSpace(serverName));
   Assert.IsFalse(String.IsNullOrWhiteSpace(databaseName));

   var cmdBuilder = new StringBuilder();
   cmdBuilder.AppendFormat("sqlcmd -E -S {0} -d {1} ", serverName, databaseName);
   if (userName.Length > 0)
   {
       cmdBuilder.AppendFormat("-U {0} -P {1} ", userName, password);
   }

   // Complete the command string.
   // Run the executable.
}

// Cannot think of a good name. Emptify? MakeNullIfEmpty?
private string Strip(string source)
{
    if (String.IsNullOrWhiteSpace(source))
    {
        return String.Empty;
    }

    return source;
}