如何在C#中将参数默认值设置为DateTime.MaxValue?

13

我希望说:

public void Problem(DateTime optional = DateTime.MaxValue)
{
}

但是编译器抱怨DateTime.MaxValue不是编译时常量。

DateTime.MinValue很容易,只需使用default(DateTime)

另请参阅“如何在C#中将参数默认为Guid.Empty?

我不想使用方法重载,因为我尝试驯服的方法有101个参数!


2
@Sam Holder 但是一个拥有8.5k的OP是如何最终拥有101个方法参数的呢?我从未遇到过这种情况。我真的很想知道为什么这似乎是最佳设计。那里似乎存在着疯狂的耦合水平。直觉告诉我,如果您使用这样的方法,您可能无法获得良好的代码指标。 - Simen S
@Sam Holder 引用杰瑞·塞范菲尔德的话来说:“如果你的T恤上沾满了血迹,也许洗衣不是你目前最大的问题。”日期时间问题似乎只是参数问题的附带问题。 - Simen S
3
@Simen 好的,101个参数可能以多种方式出现。 遗留系统; 开发团队因缺乏重构时间而扩展行为(从而产生技术债务); 当然,正如这种情况一样,还有大量的讽刺。 另外,您怎么知道这101个参数是他做的? - Adam Houldsworth
1
@Simen:别费心了...那不是正确的编程实践。没有人提出过这一点。他们只是说,最终可能会得到完全违背良好编程实践的代码,这并不是不可能的。实际上,你确实问了一个问题:“OP如何”最终得到这样的代码。 - Cody Gray
显示剩余2条评论
8个回答

12

我会用类似下面的方法来替代这个:

public void Problem(DateTime? optional = null)
{
   DateTime dateTime = optional ?? DateTime.MaxValue
   // Now use dateTime
}

1
这似乎是最好的选择,鉴于我不能重写代码库。 - Ian Ringrose
7
你可能还想使用空值合并运算符来编写它,即:DateTime dateTime = optional ?? DateTime.MaxValue; - Jeppe Stig Nielsen

5
根据您的评论,您正在尝试使具有101参数的方法对调用者更加易用。
我强烈建议您创建一个参数类,并使用默认值初始化该类的属性。为您的方法提供一个重载,仅接受一个参数:参数类。
这将真正改善您的方法的使用方式,因为用户甚至可以重复使用其参数类实例,如果他只需要更改一个参数。

我更倾向于使用多个参数类。如果其中一些参数“不属于同一组”,那将很奇怪。 - Simen S
@Simen:没有了解他的代码,我们无法确定,但是你的建议很有道理,如果它们属于同一组的话。 - Daniel Hilgarth
我猜可能会有这样的情况,即一个类正在处理许多非常不相关的原子信息元素:例如,如果您试图在弱类型配置文件和应用程序核心之间定义强类型接口。尽管如此,我认为应该避免通过单个方法调用将它们全部传递。 - Simen S

4
您可以定义多个函数:
public void Problem()
{
     Problem(DateTime.MaxValue);
}
public void Problem(DateTime optional)
{
     // do your stuff here.
}

如果您调用Problem()函数(无参数),该函数将调用另一个带参数的函数。

这可能会让人感到困惑。乍一看,这两种方法的签名似乎相同。C#规范 告诉我们 ,编译器将更喜欢不带可选参数的方法,但您不应该指望每个人都期望这种行为。其他建议的解决方案更清晰且更易于维护。 - Cody Gray

3

我不熟悉C#4.0,但在C#3.5中,我会使用重载;

public void Problem()
{
    Problem(DateTime.MaxValue);
}
public void Problem(DateTime dt)
{
}

你可以使用以下任意一种方式调用它:

Problem(); //defaults to maxvalue
Problem(myDateTime); //uses input value

编辑: 回应一些评论:

public class FooBar
{
    public bool Problem()
    {
        //creates a default person object
        return Problem(new Person());
    }

    public void Problem(Person person)
    {
        //Some logic here
        return true;
    }
}

public class Person
{
    public string Name { get; private set; }
    public DateTime DOB { get; private set; }
    public Person(string name, DateTime dob)
    {
        this.Name = name;
        this.DOB = dob;
    }

    /// <summary>
    /// Default constructor
    /// </summary>
    public Person()
    {
        Name = "Michael";
        DOB = DateTime.Parse("1980-07-21");
    }
}

3
@Ian: 哈哈哈,天哪!!我认为你在那里完全有一个不同的问题!使用参数类。101个参数......! - Daniel Hilgarth
@Ian Ringrose,任何给定方法或构造函数中都不应该有超过5个参数。正如@Daniel建议的那样,将这些参数抽象成一个ProblemsArgs类,并传递它。 - firefox1986
@Ian-Ringrose 请查看传递 args 类的示例编辑。 - firefox1986

3
您要求的操作是不可能实现的。 DateTime.MaxValue 不是编译时常量;它实际上是一个只读字段,在运行时由静态构造函数初始化。这里的区别变得非常关键。可选参数需要编译时常量,因为它们直接将值嵌入到代码中。
然而,真正的问题在于您的方法需要101个参数。我从未见过如此强烈地呼吁重构的东西。我的建议是将方法更改为接受类的实例。这也将为您提供更多灵活性,以指定类的单个属性的默认值。特别地,您将能够指定不是编译时常量的值。

2
简单的回答是,我认为你不能使用可选参数来完成这个任务。如果这只是一个参数的例子,那么你可以使用重载方法。但如果这是一个有很多可选参数的方法,那么这可能不可行。
你可以将其设置为 DateTime? 并传递 null,然后在方法中将 null 解释为 DateTime.MaxValue
有一篇关于可选参数的好文章,我会找出来给你看。 编辑 文章在这里

-1: 你的建议非常糟糕,因为null通常被视为“default(T)”的等价物。你的方法会严重改变语义。正确的方式是使用重载。 - Daniel Hilgarth
1
@Daniel 很少会用到 default(DateTime) ,但是配合后续的内部检查,这完全是一个有效的替代方案...即使使用方式不变,因为给它一个空的 DateTime?仍然会触发默认值。 - Adam Houldsworth
如果一个方法有很多参数并且 OP 只是为问题举了一个例子,那么重载可能不可行。如果这是唯一的参数,那么重载会更好。我只是提供了一种替代方案,如果他想使用可选参数,因为我认为他不能以其他方式获得所需的行为,而仍然将其作为可选参数。 - Sam Holder
@Adam:我所说的是POLS。当使用null值调用一个方法时,我不希望它被解释为MaxValue - Daniel Hilgarth
1
@Daniel,即使参数被称为“endDate”?我认为这完全取决于上下文。根据情况,您可能希望将null表示为不同的含义,例如具有2个参数StartDate和EndDate的方法,两者都可以为null,并且可能都默认为不同的值,startDate为DateTime.MinValue,EndDate为DateTime.MaxValue,在特定情况下,这可能是明智的,事实上,我曾经看到过一个用于时间跨度的类就是这样做的。我只是给OP提供了一个选项,而不是显而易见的“创建重载”,如果那样简单,我认为他会这样做的。 - Sam Holder
显示剩余2条评论

2

如果您在其中一条评论中提到的方法有很多参数,您可以将它们全部转换为参数类,并使用其属性初始化程序。然后您就不必初始化所有属性,可以在该类的构造函数中将日期设置为 DateTime.MaxValue


1

loadDefault参数值是常量,也就是说,它不能是string.Empty/Guid.Empty等。您可以使用方法重载:

void M(int intValue)
{
   M(intValue, Guid.Empty);
}
void M(int intValue, Guid guid)
{
   //do something
}

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