What is the most appropriate way to handle corrupted input data in a C # constructor?

advertisements

I'm reading data in from a file and creating objects based on this data. The data format is not under my control and is occasionally corrupt. What is the most appropriate way of handling these errors when constructing the objects in C#?

In other programming languages I have returned a null, but that does not appear to be an option with C#.

I've managed to figure out the following options, but I would appreciate advice from more experienced C# programmers:

Option 1. Read the file inside the constructor and throw an exception when the source data is corrupt:

try
{
    obj = Constructor(sourceFile);
    ... process object ...
}
catch (IOException ex)
{
    ...
}

Option 2. Create the object, then use a method to read data from the source file:

obj = Constructor();
obj.ReadData(sourceFile);
if (obj.IsValid)
{
    ... process object ...
}

or possibly throw exceptions on error:

obj = Constructor();
try
{
    obj.Read(sourceFile);
    ... process object ...
}
catch
{
    ...
}

Option 3. Create the object using a static TryParse method:

if (ObjClass.TryParse(sourceFile, out obj))
{
    ... process object ...
}

and if so, should I implement option 3 internally using option 1?

public static bool TryParse(FileStream sourceFile, out ObjClass obj)
{
    try
    {
        obj = Constructor(sourceFile);
        return true;
    }
    catch (IOException ex)
        return false;
}


I would do something along the lines of option 3):

class ObjectClass
{
    protected ObjectClass(...constructor parameters your object depends on...)
    {
    }

    public static ObjectClass CreateFromFile(FileStream sourceFile)
    {
        .. parse source file
        if (parseOk)
        {
            return new ObjectClass(my, constructor, parameters);
        }
        return null;
    }
}

And then use it like this:

ObjClass.CreateFromFile(sourcefile);

In general the constructor should take as parameters all properties which essentially define the class. Doing heavyweight calculations (like parsing a file) is best left to factory methods as it is usually not expected for the constructor to perform complex and potentially long running tasks.

Update: As mentioned in comments a better pattern is this:

    public static ObjectClass CreateFromFile(FileStream sourceFile)
    {
        .. parse source file
        if (!parseOk)
        {
            throw new ParseException(parseErrorDescription);
        }
        return new ObjectClass(my, constructor, parameters);
    }

    public static bool TryCreateFromFile(FileStream sourceFile, out ObjectClass obj)
    {
        obj = null;
        .. parse source file
        if (!parseOk)
        {
            return false;
        }
        obj = new ObjectClass(my, constructor, parameters);
        return true;
    }