0

I have type T and I'd like to check if its safe to pass to Activator.CreateInstance(T).

What comes to my mind is to do this:

if(!T.IsInterface && !T.IsAbstract)
{
    instance = (T)Activator.CreateInstance(T);
}

BUT:

  • Is this enough? Did I not miss a necessary test? Is it possible that a type is not an interface and is not an abstract class but nevertheless still cannot be instantiated? Given my knowledge of C# is still quite rudimentary I think it's very possible I missed a corner case or two.
  • Do I have to write a test manually? Is there not something like T.IsInstantiable or whatever included in the language?

EDIT: No, T is not coming from a generic constraint. This is the piece of code T is coming from:

var instances = System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
    .Where(
        // some other constraints
    ).Where(
        // can be instantiated, I'm trying to figure this part in my question
    ).Select(
        T => Activator.CreateInstance(T)
    );
  • @RyanWilson Yes precisely, I told you I must had missed something :) –  Nov 01 '18 at 19:36
  • 3
    Also, would need a constructor without any arguments. – JSteward Nov 01 '18 at 19:36
  • what about private constructors? you can't instantiate such classes outside of their own methods. – adjan Nov 01 '18 at 19:37
  • `if(T.GetConstructor(Type.EmptyTypes) != null && !T.IsAbstract)` Should do it. This will check to make sure the class is not abstract and it will check to make sure there is an empty constructor. – Icemanind Nov 01 '18 at 19:37
  • @gaazkam I was wrong about static, static classes are returned as Abstract and Sealed, but there are other good points made here, like about private constructors. This SO post looks like it will give you everything you need (https://stackoverflow.com/questions/1175888/determine-if-a-type-is-static) – Ryan Wilson Nov 01 '18 at 19:38
  • Just call `Type.GetConstructors` and check for that onne having no arguments using `ConstructorInfo.GetParaeters`. – MakePeaceGreatAgain Nov 01 '18 at 19:50
  • Another case would be checking if IsGenericTypeDefinition is false. Open generic types, like `List`, cannot be instantiated, but a type like `List` can be. – Mike Zboray Nov 01 '18 at 19:51

1 Answers1

1

If T is a generic argument, just use the new() constraint on it. That way the compiler will enforce this, not the runtime

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • It's not. `T` comes from `System.Reflection.Assembly.GetExecutingAssembly().GetTypes().Where(/*otherconstraints*/).Where(/*canBeInstantiated*/).Select(T => Activator.CreateInstance(T)` –  Nov 01 '18 at 20:14
  • 2
    @gaazkam k. thats fair, but you won't be able to cast it then. – Daniel A. White Nov 01 '18 at 20:25