DateTime 可选参数的默认值应该是什么?

30

通常情况下,如果我有一个可空类型的可选参数,我会把 null 作为默认值。这样我就知道,如果该值为 null,则调用方不想为该值指定任何值。

public void Foo(string text, string text2= null);

如果参数通常是正整数,我可以使用负数

public void Foo(string text, int index=-1);

DateTime怎么样?它不可为空,而且(据我所知)它也没有不能成为真正输入的无意义数字(比如说正整数为-1)。或者有吗?在这种情况下你会使用什么?

我也知道我可以使用可空的DateTime类型,但这意味着方法调用者将不得不使用Nullable而不是方便地传递一个DateTime。


10个回答

38

你可以使用 C# 中的 ? 运算符使值类型可为空:

DateTime? myDate = null;

有了这个,你就可以将参数变成可选的:

void Foo(DateTime? myDate = null)
{
}

可空类型的进一步阅读。

然而,这不是唯一的解决方法,您可以使用default(DateTime),但是您不能在可选参数中使用DateTime.MinValueMaxValueNow,因为它们不是编译时常量。

当然,您不需要使用可选参数,如果您希望使用Min、Max或Now,则可以使用重载方法。

void Foo()
{
    Foo(DateTime.MinValue);
}

void Foo(DateTime d)
{
}

如果你想要过度设计(好吧,也许不是过度设计,有很多合理的原因可以这样做),那么你可以定义一个新的日期类型,它能够理解自己是否具有值:

class SmarterDateTime
{
    public bool IsSet { get; set; }

    // Wrapper around DateTime etc excluded.
}

关于默认值应该选择什么,您可以选择任何日期作为默认值,但对于可选参数之类的内容,您将有限制。

个人而言,我倾向于使用DateTime.MinValue


我知道,但这有点不太理想,因为调用者代码也必须使用可空类型来调用它。 - Louis Rhys
2
@LouisRhys:它们不会明确地这样做 - 从DateTimeDateTime?存在隐式转换。 - Jon Skeet
@JonSkeet @adam 在吗?但是,我仍然记得有时候我会遇到这样的情况:我期望代码可以使用 DateTime 工作,但不能使用 DateTime?(虽然我不确定具体是哪段代码)。 - Louis Rhys
2
@LouisRhys:如果你使用了ref参数,或者尝试将一个DateTime?值赋给一个DateTime变量,那么就会出现这种情况。 - Jon Skeet
1
@JonSkeet 这是否意味着,如果它只是一个非 ref 参数,调用者将不会受到任何影响? - Louis Rhys
2
@LouisRhys:好吧,这不会是一个二进制兼容的更改,并且还有一些其他角落情况(委托的方法组转换),但对于“正常”的方法调用应该没问题。 - Jon Skeet

18

默认 (DateTime) - operator default 适用于 It


1
它的实际价值是多少? - Louis Rhys
4
对于其他人的疑问,实际值为:1-1-0001 0:00:00 - natli
2
它相当于 DateTime.MinValue(第一年的第一个月的第一天午夜)。 - Kjartan
default(DateTime?) 为 null。 - spacebread

9

当被问到“DateTime的默认值是什么”时,回答应该是:你只能使用 default(DateTime)。这是因为默认值必须是 const,而 DateTime.MinValueDateTime.MaxValue 都只是 static readonly,但请注意

default(DateTime) == DateTime.MinValue

向下转到Kind

如果您愿意,可以实现一个少一个参数(DateTime)的重载,并从该重载调用“主”方法传递您喜欢的值。

但是,正如其他人所写的那样,问题在于您编写了错误的前提条件。

不,DateTime(几乎所有的ValueType都是这样。几乎所有的,因为Nullable<Nullable<int>>是非法的,即使Nullable<T>是一个ValueType是可空的Nullable<DateTime>DateTime?(同一件事)

甚至int也是可空的,您知道吗? int? :-)


6

DateTime.MinValue将是默认值。


4

请检查dateTime默认参数,它的值应为1/1/0001 12:00:00 AM

private void M(Int32 x = 9, String s = “A”, DateTimedt = default(DateTime), Guidguid = new Guid()) {
Console.WriteLine(“x={0}, s={1}, dt={2}, guid={3}”, x, s, dt, guid);
}

3

如果您使用Nullable,您的函数调用者可以将普通DateTime参数传递给它,因此他们不会注意到任何问题 :) 这里有一些隐式操作符可以帮助您实现这个功能。

如果您想在函数中设置默认值,您可以这样做:

public void Foo(DateTime? value = null)
{
    if ( value == null )
    {
        value = ... // default
    } 
}

2

代码片段

public DateTime method1()
{

  if (condition)

    return new DateTime(2007, 5, 30, 11, 32, 00);

  else

    return default(DateTime);

}

默认语句将把值类型初始化为其默认值。对于日期时间而言,该值也作为名为DateTime.MinValue的静态属性公开。如果使用C#1.0,则“default(DateTime)”语句相当于“DateTime.MinValue”。您可以将此特殊值用作一种“标记”值,这意味着如果返回它,则表示无效的日期时间。
如果再次使用C#2.0,则还可以使用所谓的可空类型,并且实际上返回NULL,如以下示例所示。
代码片段
public DateTime? method2()
{

  if (condition)

    return new DateTime(2007, 5, 30, 11, 32, 00);

  else

    return null;

}

使用MVC时,我有一个可选的DateTime,但是我调用的函数尝试将其转换为datetime时无法工作。在函数返回类型中添加? 完全解决了它..谢谢! - da_jokker

1
    // This is the best way to null out the DateTime.
    //
    DateTime dateTime2 = DateTime.MinValue;

3
那并不会使DateTime变为空值,它仍然是一个有效的值。你如何区分有意设置的值和不存在的值? - Jon Skeet

1

您可以考虑使用值DateTime.MinValue并进行重载。


0

这取决于您的使用情况。

任何不匹配真实数据的都可以使用,但这取决于您对其的使用(因此对于整数来说,-1是完全好的,只有在您使用它时仅需要正整数才有意义)。

如果您发送最小日期(感兴趣的所有foo都晚于该日期),则任何早于最早合理日期的日期都可以,并且像.Where(f -> f.When > myDate)这样的代码将无需查找该特殊情况即可工作。

同样,反向最大日期也是如此(任何日期都会在最新合理日期之后)。

否则,完全避免使用默认值,而是进行重载。


你所说的“overload instead”,是指在两个方法中重复方法体吗? - Louis Rhys
理想情况下,最好将尽可能多的代码通过一种方法调用另一个方法或两个方法都调用私有方法来共享。具体采用哪种方式取决于在这些方法中所做的事情。 - Jon Hanna
是的,我同意,但如果一个调用另一个或两个都调用相同的方法,我们仍然需要解决原始问题,不是吗? - Louis Rhys
只有在这种情况下才会出现,即使是这样,它也可以避免签名中的默认值必须是编译时常量的限制。还有一些情况可以相互调用,我们不必解决它,例如 IQueryable<Doc> GetDocs(int catID, DateTime published){return GetDocuments(catID).Where(d => d.Published == published);} 它根本不需要担心这个问题。 此外,你忽略了 DateTime?,但忽略了一个带有 DateTime? 参数的方法可以使用 DateTime 参数进行调用,因此同样方便。 - Jon Hanna

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