如何创建两个构造函数重载,都只接受一个字符串参数?

7
例如,您希望以两种方式之一可能初始化对象,使用文件路径和字符串。通常,两个构造函数都应该只接受一个字符串参数,即MyObject(string file)MyObject(string content),但是这样无法重载。您有什么建议吗?
编辑:在第一种情况下,文件路径也是必需的,请不要提出读取文件内容并将其传递给其他构造函数的解决方案。

3
将字符串类型中的一个包装在自己的类中,并将该类型作为参数接受。 - Cody Gray
@Cody Gray:你好,我认为这值得成为一个答案。 - Louis Rhys
我没有将它发布为答案,因为我认为Mark Byers提供的那个是这种情况下最好的解决方案。(我改为点赞了那个答案。)当已经有一个内置类型可以完成工作时,没有必要创建额外的包装类。然而,对于更一般的应用程序,我的建议可能是正确的选择。 - Cody Gray
我会选择静态工厂方法或创建一个接受两个参数的构造函数,并在两个参数都不为 null 时抛出异常。我之所以这么说是因为并不总是(我的情况 - 我有一个类似的问题)类型真的是字符串,而且我觉得添加一个表示字符串的新类并不特别优雅。 - Żubrówka
7个回答

17

我不是C#程序员,但这看起来像是静态工厂方法模式的工作:static factory method模式

class MyObject {
  public static MyObject FromContent(string content) {
    return new MyObject(content);
  }

  public static MyObject FromFile(string path) {
    return new MyObject(ReadContentFromFile(path));
  }
}

那么你可以这样做

MyObject object = MyObject.FromFile("/some/path");

这甚至比使用常规构造函数更易读。


在第二种情况下,我仍然需要路径,如果使用这种模式,我将失去它。 - Louis Rhys
你无论如何都会遇到这个问题,对吧?为什么不使用MyObject.GetPath()呢?如果MyObject不是从路径创建的,则返回null。 - sjr
2
@Louis:为路径创建一个私有的设置器,以便MyObject.FromFile()可以使用该信息来存储。或者创建一个私有构造函数重载,该构造函数需要一个额外的虚拟参数来指示字符串是路径——这些可能是设计上的瑕疵,但由于它们是私有的,并且生成的公共接口是干净的,所以这可能是一个合理的权衡。 - Michael Burr

11

也许您可以将第一个参数更改为接受 FileInfo

class MyObject
{
    public MyObject(FileInfo file) { /* etc... */ }
    public MyObject(string content) { /* etc... */ }
}

...

MyObject o = new MyObject(new FileInfo(filename));

更一般地说,将字符串类型之一封装在自己的类中,并接受该类型作为参数(在本例中包装器是FileInfo)。 - Louis Rhys

1
或者创建工厂方法:
public static MyObject CreateByFilePath(string path){ ... }
public static MyObject CreateByContent(string content){ ... }

1

也许你可以使用工厂模式?

class MyObjectProvider
{
   public static MyObject CreateByPath(string path) 
   { 
      return new MyObject
              {
                  Path = path;
              };

   }

   public static MyObject CreateByContent(string content) 
   { 
      return new MyObject
              {
                  Content = content;
              };
   }
}

1

0
public MyObject(Uri fileUri);
public MyObject(string content);

0
我会采取反对意见,建议不要这样做。到目前为止,已经发布的最佳解决方案之一(使用替代类型,如FileInfo或Uri)对我来说似乎有点hackish - 违反了最少惊讶原则。
如果您可以仅使用内容构造而不需要文件名,则可以得出文件名不是必需的结论。同样,如果您只能使用文件名构造,则可以得出内容不是必需的结论。可以随后设置缺少的文件名/内容,例如通过设置属性:
MyObject myObject = new MyObject(fileName);
myObject.Content = ...

MyObject myObject = new MyObject(content);
myObject.FileName = ...

与其试图对抗它,不如选择一个参数作为最重要的参数(下面的示例中为 fileName),并创建以下两个构造函数:

public MyObject(string fileName) : this(fileName, null)
{
}

public MyObject(string fileName, string content)
{
    ... implementation
}

如果有意义的话,您可以允许将 null 传递给任一或两个参数。如果合适,您也可以坚持至少一个参数不为 null:

public MyObject(string fileName, string content)
{
    if (fileName == null && content == null) throw new ArgumentException(...);
    ...
}    

简而言之,不要使用黑客手段来绕过这样的限制。

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