MTR
MTR

Reputation: 1740

How to check a type for parameterless constructor?

Because I want to avoid an exception, I want to check whether a type has a parameterless constructor. How can I achieve this?

I need something like this:

bool HasDefaultConstructor<TT>(TT source)
{
   return ???;
}

EDIT: I want to create an object of same type as source and if it hasn't a default constructor I want to use default(TT) instead.

What I have right now is:

        static TT CreateObject<TT>(TT source)
    {
        try
        {
            if(!HasDefaultConstructor<TT>(source))
            {
                return default(TT);
            }
            return (TT)Activator.CreateInstance(source.GetType());
        }
        catch(Exception ex)
        {
            Trace.WriteLine("Exception catched!\r\n" + ex);
        }
        return default(TT);
    }
    static bool HasDefaultConstructor<TT>(TT source)
    {
        ConstructorInfo c = typeof(TT).GetConstructor(new Type[] { });

        return c != null;
    }

But the check gives me true and CreateInstance throws exception

No parameterless constructor

Solution:

bool HasDefaultConstructor(Type t)
{
   return t.GetConstructor(Type.EmptyTypes) != null;
}

There were many recursive functions and iterations involved and somewhere down this way, the wrong generic function HasDefaultConstructor (with type object) has been called. Using a non generic function did the trick.

Thank you all for your constructive help.

Upvotes: 8

Views: 3403

Answers (2)

Adi Lester
Adi Lester

Reputation: 25211

GetConstructor(Type.EmptyTypes) will return the parameterless constructor, or null if one does not exist, so you can have:

return typeof(TT).GetConstructor(Type.EmptyTypes) != null;

EDIT

I'm guessing your problem is that TT and source.GetType() are actually two different types. source.GetType() probably derives from TT but has no parameterless constructor. So what you actually need to do is make the check for source.GetType():

bool HasDefaultConstructor(Type t)
{
   return t.GetConstructor(Type.EmptyTypes) != null;
}

if(!HasDefaultConstructor(source.GetType()))
    ...

Upvotes: 13

Patrick Hofman
Patrick Hofman

Reputation: 157098

Use reflection to check if the type has a parameterless constructor. Use Type.GetConstructor:

bool HasDefaultConstructor<TT>()
{
    ConstructorInfo c = typeof(TT).GetConstructor(new Type[] { });
    // A constructor without any types defined: no parameters

    return c != null;
}

If you just want to create an instance of TT, use the new constraint:

TT CreateUsingDefaultConstructor<TT>() where TT : new()
{
    return new TT();
}

As Jeppe Stig Nielsen suggested, you could use this code to also find constructors that are not public. In my opinion, you should only use this as a last resort!

typeof(TT).GetConstructor( BindingFlags.Instance
                           | BindingFlags.NonPublic
                           | BindingFlags.Public
                         , null
                         , new Type[] { }
                         , null
                         )

Upvotes: 9

Related Questions