web-dev-qa-db-ja.com

C#4.0-オプションの文字列パラメーターの処理方法

このコードは無効です:

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

しかし、このコードは:

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

どうして? string.Emptyは定数ではなく読み取り専用フィールドであるため、オプションのパラメーターのデフォルトはコンパイル時の定数でなければなりません。

だから、私の質問に...(まあ、心配)

これは私がしなければならなかったことです:

private const string emptyString = "";

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

オプションの文字列パラメーターをどのように処理しますか?

String.Empty をコンパイル時の定数にできないのはなぜですか?

16
RPM1984

うーん...文字列optionalParm = ""の何が問題になっていますか?なぜそれが悪いのですか?この場合、空の文字列のシンボリック定数が本当に必要だと思いますか?これはどうですか?

const int Zero = 0;

void SomeMethod(int optional = Zero) { }

それはあなたにはまったくばかげているように見えますか?

11
Ed S.

""値が気に入らない場合は、default(string)を使用できます。
私はそれで遊んで、それは許可されています。

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

コード分析警告1026 は、オプションのパラメーターを使用しないことを示しています。次のように、オーバーロードメソッドを使用することをお勧めします。

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

それらを処理する最良の方法は、

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

したがって、String.Emptyは使用できません。誰もが「」を認識しますが、もし私が見つけたらoptionalString = nullStringどうすればよいかわからない。 それ以外の場合は、モノにemptyString--それはnullではありません!

2
STW

私はこの質問に答えています。

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

Mscorlib.dllのString.csのリフレクターを介した逆アセンブルコードを以下に示します。

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

したがって、Windowsプラットフォームでは、string.Emptyは正確に ""です。しかし、ご存知ですか、MartianのOSでは、EmptyとWhitespaceCharsの定義が異なります。

1
Cheng Chen

Null、 ""、および空白文字を同じように失って処理しても構わない場合は、デフォルトでnullを使用できます。これは、dbへの信頼できる接続の可能性があるため、ユーザー名とパスワードがオプションのフィールドである場合に非常に便利です。このロジックを変更して、文字列をnullにリセットし、アサートと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;
}
0
Hamish Grubijan