1

I'm trying to make an extension method like this:

public static T Optional<T>(this T obj)
{
    return obj != null ? obj : Activator.CreateInstance<T>();
}

However, it fails if there isn't a parameterless constructor for the type. Is there a way I can get an instance of an object without a parameterless constructor?

NOTE: I don't want to put where T : new() and limit the method to only classes with parameterless constructors.

Kyle
  • 21,377
  • 37
  • 113
  • 200
  • So you want to create instances of classes that expect to be created with a non-parameterless constructor? – Jeroen Wiert Pluimers Nov 05 '10 at 22:14
  • @jeroen - Yes, I'm trying to implement a form of the safe navigation operator that some languages have. To allow me to do obj1.Optional().Value.Optional().Member without having to do null checks along the way. – Kyle Nov 05 '10 at 22:23
  • How will you know how to initialize the class then? Depending on what the constructor is designed to do, Bad Things could potentially happen. – Daniel Pryden Nov 05 '10 at 22:28
  • 2
    How will you know what values to pass into the constructor? You can't rely on `default(T)` being a valid argument for every class ever. – Joel Mueller Nov 05 '10 at 22:28
  • @Joel Mueller: Indeed. What about class `FireTheNukes` with the only constructor `FireTheNukes(int numberOfPeopleToAllowToLive)`? – Daniel Pryden Nov 05 '10 at 22:43

1 Answers1

0

You could create a factory method to create instances of your objects. If it doesn't have a default constructor, supply the arguments. Something like this:

public static class Factories
{
    public static Func<T> GetInstanceFactory<T>(params object[] args)
    {
        var type = typeof(T);
        var ctor = null as System.Reflection.ConstructorInfo;
        if (args != null && args.Length > 0)
            ctor = type.GetConstructor(args.Select(arg => arg.GetType()).ToArray());
        if (ctor == null)
            ctor = type.GetConstructor(new Type[] { });
        if (ctor == null)
            throw new ArgumentException("Cannot find suitable constructor for object");
        return () => (T)ctor.Invoke(args.ToArray());
    }
}

// usage
var oooooFactory = Factories.GetInstanceFactory<string>('o', 5); // create strings of repeated characters
oooooFactory(); // "ooooo"
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272