在C#中如何将参数设置为null?

20

在Stack Overflow上阅读后,我得知在检查DateTime格式的情况下应该使用DateTime.TryParse。尝试了一些正则表达式后,它们似乎变得很长而且难以覆盖许多格式。

但是TryParse方法需要一个“out”参数,由于我只想进行格式验证检查,所以不需要实际的结果。

因此,我现在只有一个保存了“out”结果的变量,却无法对其进行任何操作。是否有一种方法可以避免使用out参数呢?

这样可以消除警告并停止让这个变量在代码中闲置。

6个回答

37

从C#7.0开始(自2016年8月),您可以使用out var结构,然后在随后的代码中忽略新的var。

bool success = DateTime.TryParse(value, out var result);

如果您真的不关心结果的值,请使用discards

bool success = DateTime.TryParse(value, out _);

2
这应该是最高得票的答案。'result'立即超出作用域。 - fafrd
1
这将在同一作用域内保留代码中的“result”。在方法内,您可以检查成功并具有结果值(或默认(DateTime))。此外,在C#7之前不支持此表示法。 - jeubank12

22

不是的。我会将它包装在一个方法中,以便使主要代码更加清晰:

  bool IsValidDate(string value)
  {
     DateTime result;
     return DateTime.TryParse(value, out result); //result is stored, but you only care about the return value of TryParse()
  }

6
我会考虑将省略号扩展为您答案中的实际参数。 - MPritchard
@Martin -- 谢谢,是的,我也考虑过这个问题,但由于我们不知道 chobo2 将使用什么格式字符串,所以我认为他比我更了解细节。 - Kim Gräsman
我没有真正设置格式提供程序。 我在Web配置中设置为美国文化,因此所有日期都应以美国日期格式显示。 - chobo2
如果我有很多输出参数要使用,那么我会这样做,但是对于一个参数,我不会进行包装。我只是希望有一种使用 null 或其他方式的方法。不过将来知道这个也是好的。 - chobo2

7

我并不建议你真的这样做,但你可以使用一个单独的帮助类来使得所有的输出参数变得更加容易:

public static class OutHelper<T>
{
    [ThreadStatic]
    public static T Ignored;
}

然后你可以调用:

if (DateTime.TryParse(text, out OutHelper<DateTime>.Ignored))

这真是太糟糕了,它使用一个公共的可变字段,如果你的应用程序也在执行某些恶意代码,则该代码可以访问你解析的最后一个值...但它应该能正常工作 :)


1
@Mehrdad:它不是线程安全的方式是什么?想法是你从来没有从值中读取过,所以谁在乎它被写入多次呢?如果你调用的方法首先写入了输出参数,然后再读取它,那么这可能会导致失败...但无论如何,这听起来都是一个坏主意。显然,总体而言,这仍然是一个可怕的想法 :) - Jon Skeet
1
@Jon:我指的是当被调用者将out参数用作临时存储并在完成后也包含返回值的情况。虽然对于被调用者假设它不会改变是个坏主意,但这是一种自然的期望。使用全局变量来达到这个目的严重破坏了这种假设。无论如何,正如你所提到的,这基本上是一种“技巧”,在实践中应该避免使用。 - Mehrdad Afshari
说实话,使用在多个线程之间共享的任何变量都可能存在这个问题。例如它可以是某个对象的实例变量。我想,在使用输出变量时要注意这一点... - Jon Skeet
2
@Mehrdad:我刚想到,这很容易解决...编辑 :) - Jon Skeet

4
如果您正在使用.NET 3及以上版本,您可以随时创建一个扩展方法?
public static bool IsValidDate(this string value)
{
  DateTime date = DateTime.Null;
  return DateTime.TryParse(value, out date);
}

[已编辑,将方法名更改为更合适的名称]


2
在将变量作为“out”参数传递之前,您无需对其进行初始化。仅声明即可。 - Mehrdad Afshari
没错。这只是我有的一种防御性习惯。 - Pete OHanlon
10
实际上,在C#中,这种“防御性”的习惯最好是不必要的,而且在更糟糕的情况下实际上是有害的,因为编译器本身将强制变量进行明确定义初始化,并且如果变量在使用之前未被初始化,则编译器将无法编译。如果您在不真正需要时初始化变量,然后忘记将其作为“out”参数传递给方法,“防御性”会使错误悄悄地消失。 - Mehrdad Afshari

4

不,你不能摆脱这个变量,但你也不应该收到编译器的警告。

将一个变量作为 out 参数传递是“使用”该变量。编译器不会因此发出警告。


你是对的,我以为我已经得到了一个猜测,但更新速度很慢。 - chobo2

1

TryParse 是更好的选择。这只是一个浪费的变量。其他选项包括在 try-catch 块中使用 Convert.ToDateTime()。但是,这也不是很有效率,因为 try-catch 块通常比较重。下一个选项是正则表达式。这是更好的解决方案。我想这比其他方法更快地给出结果。

你可以像 Kim Gräsman 所说的那样很好地封装这个方法...


最终,我身边有一个变量其实并不是什么大问题,但我真的认为你应该能够使用null或其他东西。或者他们应该只有一个解析器,只检查而不返回任何内容。 - chobo2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接