使用调用构造函数的静态方法有什么好处(语义或其他)?

时间:2014-06-20 01:46:33

标签: c# constructor static-methods

我刚刚更新了Visual Studio 2013,我注意到在MVC应用程序的项目模板中,ApplicationDbContext类现在有一个只调用构造函数的静态方法:

public static ApplicationDbContext Create()
{
    return new ApplicationDbContext();
}

这对我来说似乎很混乱,但我想有一些语义原因我现在应该开始使用ApplicationDbContext.Create()而不是new ApplicationDbContext()。这样做有什么好处吗?

3 个答案:

答案 0 :(得分:17)

实际上。是

在您的特定情况下,通过它包装它可以让您快速开始使用逻辑,例如制作ApplicationDbContext和singleton或以整个应用程序的通用方式处理异常。由于构造函数不能返回null,因此能够捕获异常并返回null非常重要。

Tuple.Create是泛型推理的主要示例,它不适用于构造函数。这允许你说

Tuple.Create(Item1, Item2.. ItemN);

让编译器推断类型,而不是

new Tuple<T1, T2...Tn>(Item1, Item2...ItemN);

哪个更详细,如果你想切换其中一种类型,需要做更多的工作。

还存在匿名类型的情况,无法明确指定,因此不能在新语句中使用。我特意有机会在搜索特定属性的程序集以链接命令结构时,我想在搜索期间使用匿名类型创建一个可枚举的(在本例中为一个Queue),以便将类引用与其构造函数配对和字符串参数,而不是每次他们需要时查找这些参数。由于我可以在方法中再次使用Generic推理,因此我能够将构造函数包装在扩展方法中并完成工作。

还有单例模式的情况,其中你需要&#34; GetInstance&#34;通常创建值的方法,如果存在则获取值。可能不符合条件,因为它比包装构造函数稍微多一点。

此外,在很多情况下,您可能希望控制实现过程,例如将它们强制转移到其他线程,将它们记录在数据库中以便稍后撤消,或者在权限系统上进行操作,所有这些都可以通过制作构造函数包装器并添加更多逻辑行,然后对构造函数进行私有化以避免直接调用它来完成。

在某些情况下,我创建了一个工厂方法,该方法委托给已知的子级,以便根据提供的参数提供返回接口或抽象的不同实现。这具有能够隐藏实现类的额外好处--Type类和IEnumerable接口使用此模式。

答案 1 :(得分:6)

此模式非常有用,特别是如果您使用私有构造函数,并从Create返回接口类型,而不是具体类型。

private ApplicationDbContext()
{

}

public static IApplicationDbContext Create()
{
    return new ApplicationDbContext();
}

现在,您的班级消费者无法依赖具体实施 - 他们只能依赖抽象。

答案 2 :(得分:0)

使用静态方法(创建方法)包装构造函数允许您选择传达信息的特定名称。您还可以使用相同的参数签名创建多个方法,例如CreateX(float f)CreateY(float f),这是构造函数无法做到的。

这种情况非常有用,例如:用于创建表示可能具有多个单位的物理量的结构,例如时间,长度或重量。在这里,您可以使用创建方法来强制程序员始终显式指定单元,而不是仅将单位数传递给单个构造函数(假定某个单位,并且错误可能有huge consequences)。

示例:

public struct Length
{
  private const double MetersPerYard = 0.9144;
  private double _meters;

  private Length(double meters)
  {
    _meters = meters;
  }

  public static Length FromMeters(double meters)
  {
    return new Length(meters);
  }

  public static Length FromYards(double yards)
  {
    return new Length(yards*MetersPerYard);
  }

  public double Meters 
  {
    get { return _meters; } 
  }

  public double Yards
  {
    get { return _meters / MetersPerYard; }
  }
}

或者查看TimeSpan以及FromMinutesFromSeconds等方法。