Louis Rhys
Louis Rhys

Reputation: 35647

How to create two constructor overloads, both taking only one string parameter?

For example, you want an object to be possibly initialised in two ways, using a file path and using a string. Normally both constructors should take one string parameter, MyObject(string file) and MyObject(string content), but it is impossible to overload this way. What do you suggest?

Edit: In the first case, the file path is also needed, so please don't suggest a solution that reads the file content and just pass the content to the other constructor.

Upvotes: 7

Views: 3459

Answers (7)

to StackOverflow
to StackOverflow

Reputation: 124814

I'll take the contrarian approach and say don't do it. The best of the solutions posted so far (use an alternate type such as FileInfo or Uri for one of the overloads) seems a bit hackish to me - goes against the principle of least surprise.

If you can construct using the content only without a filename, it follows that the filename is not essential. And similarly if you can construct with a filename only it follows that the content is not essential. Presumably you can subsequently set the missing filename/content later, e.g. by setting a property:

MyObject myObject = new MyObject(fileName);
myObject.Content = ...

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

Instead of trying to fight it, choose one of your parameters as being the most important (fileName in the following example), and create two constructurs as follows:

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

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

You can allow null to be passed for either or both parameters if it makes sense. And you can insist that at least one is not null if that's appropriate:

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

In short, don't use hacks to work around restrictions like this.

Upvotes: 0

sikender
sikender

Reputation: 5921

I think you refer this question. ::

Calling constructor overload when both overload have same signature

Upvotes: 1

Alex Zhevzhik
Alex Zhevzhik

Reputation: 3407

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

Upvotes: 0

Cheng Chen
Cheng Chen

Reputation: 43531

Maybe you can use a factory?

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

   }

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

Upvotes: 1

Adam Rackis
Adam Rackis

Reputation: 83376

Or create factory methods:

public static MyObject CreateByFilePath(string path){ ... }
public static MyObject CreateByContent(string content){ ... }

Upvotes: 1

sjr
sjr

Reputation: 9895

I'm not a C# programmer but this looks like a job for the static factory method pattern:

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

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

Then you can do

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

which is even more readable than using a regular constructor.

Upvotes: 17

Mark Byers
Mark Byers

Reputation: 839254

Perhaps you could change the first to accept a FileInfo instead:

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

...

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

Upvotes: 11

Related Questions