2009-08-18 2 views
13

Pardonnez-moi si cette question a déjà été posée et répondue. Étant donné une classe de type T, quelle est la différence entre ce qui suit?Différence entre Activator.CreateInstance() et typeof (T) .InvokeMember() avec BindingFlags.CreateInstance

T myObj = Activator.CreateInstance<T>(); 

T myObj = typeof(T).InvokeMember(null, BindingFlags.CreateInstance, null, null, null); 

Une solution est préférée à l'autre?

+2

FWIW: 'Activator.CreateInstance ()' est plus correct pour votre premier exemple, car il ne nécessitera pas une distribution du résultat à 'T'. –

+0

@Steve Guidi: Merci. Je vais mettre à jour la question. –

Répondre

11

décompilation RuntimeType.InvokeMember donne ce fragment:

if ((bindingFlags & BindingFlags.CreateInstance) != BindingFlags.Default) 
{ 
    if (((bindingFlags & BindingFlags.CreateInstance) != BindingFlags.Default) && ((bindingFlags & (BindingFlags.SetProperty | BindingFlags.GetProperty | BindingFlags.SetField | BindingFlags.GetField | BindingFlags.InvokeMethod)) != BindingFlags.Default)) 
    { 
     throw new ArgumentException(Environment.GetResourceString("Arg_CreatInstAccess"), "bindingFlags"); 
    } 
    return Activator.CreateInstance(this, bindingFlags, binder, providedArgs, culture); 
} 

En d'autres termes, InvokeMember avec ceux BindingFlags appelle Activator.CreateInstance. Il passe par plusieurs autres couches d'appel (vérifiant les liaisons, vérifiant les arguments) avant de se mettre au travail. Activator.CreateInstance<T> est beaucoup plus succincte:

public static T CreateInstance<T>() 
{ 
    bool bNeedSecurityCheck = true; 
    bool canBeCached = false; 
    RuntimeMethodHandle emptyHandle = RuntimeMethodHandle.EmptyHandle; 
    return (T) RuntimeTypeHandle.CreateInstance(typeof(T) as RuntimeType, true, true, ref canBeCached, ref emptyHandle, ref bNeedSecurityCheck); 
} 

ÉDITÉE Vous pourriez vous attendre que ce dernier soit plus rapide, mais une méthode appelée RuntimeType.CreateInstanceSlow appelle également RuntimeTypeHandle.CreateInstance à faire le travail; il est utilisé comme solution de repli si une entrée de cache Activator pour le constructeur est introuvable. Je ferais quelques tests de performance si vous cherchez la solution la plus rapide des deux.

Questions connexes