【问题标题】:How do I default a parameter to DateTime.MaxValue in C#?如何在 C# 中将参数默认为 DateTime.MaxValue?
【发布时间】:2011-07-29 04:07:16
【问题描述】:

我想说:

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

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

DateTime.MinValue 很简单,使用 default(DateTime)

另见“How do I default a parameter to Guid.Empty in C#?

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

【问题讨论】:

  • @Sam Holder 但是一个 8.5k 的 OP 怎么会在他的方法中有 101 个参数呢?我从来没有发生过这种情况。我真的很想知道为什么这似乎是最好的设计。那里似乎有一种疯狂的耦合程度。直觉上,如果你用这样的方法获得好的code metrics,我会感到惊讶。
  • @Sam Holder 引用 Jerry Seinfeld 的话:“如果你的 T 恤上满是血迹,那么现在洗衣服可能不是你最大的问题”。 DateTime 问题似乎与参数问题无关。
  • @Simen 好吧,101 个参数可以以多种方式出现。遗留系统;由于缺乏重构时间(从而产生技术债务)而扩展行为的开发团队;当然,就像这种情况一样,是大规模的讽刺。另外,是什么让你觉得这 101 个参数是他干的?
  • @Adam 我无意责怪任何人。我宁愿指出 - 就个人而言 - 我会尝试在 OP 描述的场景中重构代码,而不是试图使日期时间适合。也许我应该开始一个单独的问题线程来寻找我的“方法签名中的 101 个参数是否是正确的编程实践?”的答案?
  • @Simen:别费心了……这从来都不是正确的编程习惯。没有人提出这一点。他们只是说,最终得到完全厌恶良好编程实践的代码并不是不可能。实际上,您确实提出了“OP如何”最终得到这样的代码的问题。

标签: c# c#-4.0 optional-parameters


【解决方案1】:

我会用这个代替:

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

【讨论】:

  • 这看起来是最不坏的选择,因为我无法重写代码库。
  • @IanRingrose 您可能还想使用the null-coalescing operator 编写它,即:DateTime dateTime = optional ?? DateTime.MaxValue;
【解决方案2】:

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

【讨论】:

  • 我更多地考虑 multiple 参数类。如果这些参数中的某些参数没有“分组在一起”,那就太奇怪了。
  • @Simen:不知道他的代码,我们无法知道,但你的建议是有道理的,如果他们属于组的话。
  • 我猜可能存在单个类处理大量非常不相关的原子信息元素的情况:例如如果您尝试在弱类型配置文件和应用程序核心之间定义强类型接口。不过,我认为应该避免通过单个方法调用将它们全部传递。
【解决方案3】:

你可以定义多个函数:

public void Problem()
{
     Problem(DateTime.MaxValue);
}
public void Problem(DateTime optional)
{
     // do your stuff here.
}

如果你调用 Problem()(不带参数),该函数调用另一个带参数的函数。

【讨论】:

  • 这可能会造成混淆。这两种方法乍一看似乎具有相同的签名。 C# 规范 tells us 编译器将更喜欢 without 可选参数的方法,但您不应该依赖每个期望这种行为的人。其他建议的解决方案更清晰,更易于维护。
【解决方案4】:

您要求做的事情根本不可能。 DateTime.MaxValue 不是编译时常量;它实际上是一个只读字段,在运行时由静态构造函数初始化。 difference 在这里变得非常关键。可选参数需要编译时常量,因为它们将值直接烘焙到代码中。

但是,真正的问题是您的方法需要 101 个参数。我从未见过如此大声呼喊重构的东西。我的建议是更改您的方法以接受类的实例。这也将使您在为类的各个属性指定默认值方面具有更大的灵活性。特别是,您将能够指定不是编译时常量的值。

【讨论】:

    【解决方案5】:

    我不熟悉 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
    

    编辑: 只是为了回答一些cmets;

    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");
        }
    }
    

    【讨论】:

    • @Ian:哈哈哈,天哪!!我认为你有一个完全不同的问题!使用参数类。 101个参数...!
    • @Ian Ringrose 在任何给定的方法或构造函数中,您永远不应该有超过 5(?) 个参数。正如@Daniel 建议的那样,将这些参数抽象为 ProblemsArgs 类,然后将其传入。
    • @Ian-Ringrose 请参阅有关传入 args 类的示例编辑。
    【解决方案6】:

    简单的答案是你不能使用我不认为的可选参数。

    如果这是唯一的参数,您可以使用重载。如果这是具有许多可选参数的方法的示例,那么这可能不可行。

    您可以做的是将其设为DateTime? 并传递null,然后在您的方法中将null 解释为DateTime.MaxValue

    我会为你挖掘一个关于可选参数的好文章。

    编辑

    article here

    【讨论】:

    • -1:您的建议很糟糕,因为 null 通常被视为等同于 default(T)。您将使用您的方法大量更改语义。正确的方法是使用重载。
    • @Daniel 几乎没有,以及 default(DateTime) 以及随后的内部检查,这是一个完全有效的替代方案......即使使用不会改变,因为给它一个空 DateTime? 仍然会触发默认值。
    • 如果方法有很多参数并且 OP 只是给出问题的示例,则重载可能不可行。如果这是唯一的参数,那么是的,过载会更好。如果他想使用可选参数,我只是建议一个替代方案,因为我认为他不能以任何其他方式获得他想要的行为并且仍然将其作为可选参数。
    • @Adam:我说的是POLS。当调用一个参数为空值的方法时,我不希望这被解释为MaxValue
    • @Daniel,即使参数被称为endDate?我认为这一切都与上下文有关。根据具体情况,您可能希望 null 表示不同的含义,例如一个具有 2 个参数 StartDate 和 EndDate 的方法,它们都可以为 null 并且可能都默认为不同的值,startDate 到 DateTime.MinValue 和 EndDate 到 DateTime.MaxValue 这可能在特定情况下要明智,确实,我已经看到一个时间跨度的课程正是这样做的。我只是给了 OP 一个选项,而不是明显的“创建过载”,我认为如果它那么简单,他会这样做
    【解决方案7】:

    如果如您在其中一个 cmets 中所述,您的方法有很多参数,您可以将它们全部转换为参数类并使用其属性初始化程序。这样就不用初始化所有属性了,可以在该类的构造函数中设置日期为DateTime.MaxValue

    【讨论】:

      【解决方案8】:

      loadDefault参数值为常量,即不能为string.Empty/Guid.Empty等,可以使用方法重载:

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

      【讨论】:

        猜你喜欢
        • 2011-07-04
        • 1970-01-01
        • 2012-05-01
        • 2010-11-15
        • 1970-01-01
        • 2011-12-06
        • 1970-01-01
        • 2010-12-01
        相关资源
        最近更新 更多