关于.net:C#4.0 – 如何处理可选的字符串参数

C# 4.0 - How to Handle Optional String Parameters

此代码无效:

1
2
3
4
private void Foo(string optionalString = string.Empty)
{
   // do foo.
}

但这个代码是:

1
2
3
4
private void Foo(string optionalString ="")
{
   // do foo.
}

为什么?因为string.empty是只读字段,而不是常量,可选参数的默认值必须是编译时常量。

所以,关于我的问题…(嗯,关心)

这就是我必须做的:

1
2
3
4
5
6
7
8
private const string emptyString ="";

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

你们如何处理可选的字符串参数?

为什么不能使string.empty成为编译时常量?


嗯…string optionalparm="又有什么问题?为什么不好?在这种情况下,您真的认为需要一个符号常量来表示空字符串吗?那么这个怎么样?

1
2
3
const int Zero = 0;

void SomeMethod(int optional = Zero) { }

你觉得这有点傻吗?


如果不喜欢"值",可以使用默认值(字符串)。
我玩过,这是允许的。

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


代码分析警告1026表示不要使用可选参数。使用重载方法更好,如:

1
2
3
4
5
6
7
8
9
10
private void Foo()
{
   Foo(string.Empty);
}
private void Foo(string optionalString)
{
   // do foo.
   if (!string.IsNullOrEmpty(optionalString))
      // etc
}

处理它们的最佳方法是:

1
2
3
4
private void Foo(string optionalString ="")
{
   // do foo.
}

所以不能使用string.empty。每个人都知道",但如果我找到了optionalString = nullString,我不知道该怎么想。如果没有其他的话,把它命名为emptyString--它不是空的!


如果您愿意玩lose和treat NULL","和空白字符相同,则可以默认为null。当用户名和密码是可选字段时,由于可能存在到数据库的可信连接,这变得非常方便。您可以更改此逻辑以将字符串重置为null,从而修改assert和if。重要的是有一个一致的约定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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;
}

我在回答这个问题。

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

下面是mscorlib.dll中通过string.cs反射镜反汇编的代码。

1
2
3
4
5
6
7
8
9
10
11
public static readonly Empty;
static String()
{
    Empty ="";
    WhitespaceChars = new char[] {
        '\t', '
'
, '\v', '\f', '
'
, ' ', '\x0085', '\x00a0', '?', '?', '?', '?', '?', '?', '?', '?',
        '?', '?', '?', '?', '?', '\u2028', '\u2029', ' ', ''
     };
}

所以在Windows平台中,string.empty正好是"。但是你知道吗,火星人在他们的操作系统中对空字符和空白字符有不同的定义。