2010-01-07 42 views
13

Estoy intentando utilizar .MemberwiseClone() en una clase personalizada de la mina, pero vomita este error:No se puede acceder miembro protegido 'object.MemberwiseClone()'

Cannot access protected member 'object.MemberwiseClone()' via a qualifier of type 'BLBGameBase_V2.Enemy'; the qualifier must be of type 'BLBGameBase_V2.GameBase' (or derived from it) 

¿Qué significa esto? O mejor aún, ¿cómo puedo clonar una clase Enemy?

Respuesta

28

Dentro de cualquier clase X, solo puede llamar al MemberwiseClone (o a cualquier otro método protegido) en una instancia de X. (O una clase derivada de X)

Puesto que la clase Enemy que usted está tratando de clon no hereda la clase GameBase que usted está tratando de clonar en ella, que está recibiendo este error.

Para solucionar este problema, agregue un método público Clone-Enemy, así:

class Enemy : ICloneable { 
    //... 
    public Enemy Clone() { return (Enemy)this.MemberwiseClone(); } 
    object ICloneable.Clone() { return Clone(); } 
} 
+1

Pero pensé MemberwiseClone era un método de objeto, el cual afaik todas las clases se derivan de? – Xenoprimate

+4

Sí, pero no puedes llamar al método protegido de una clase diferente a menos que herede de ti. De lo contrario, podría llamar a cualquier miembro protegido (incluido 'MemberwiseClone') en cualquier clase simplemente heredando de esa clase. Esto haría 'protected 'casi inútil. – SLaks

+0

"protected" es otra forma de decir: solo la clase en sí sabe cuándo es apropiado hacer MemberwiseClone(). Rara vez es, google "copia profunda". –

25
  • usted no puede utilizar MemberwiseClone() directamente, debe ponerlo en práctica a través de la clase derivada (recomendado)
  • pero, a través de la reflexión, se puede engañar a él :)
  • puede utilizar esta extensión litle para las clases que no implementa ICloneable:

    /// <summary> 
    /// Clones a object via shallow copy 
    /// </summary> 
    /// <typeparam name="T">Object Type to Clone</typeparam> 
    /// <param name="obj">Object to Clone</param> 
    /// <returns>New Object reference</returns> 
    public static T CloneObject<T>(this T obj) where T : class 
    { 
        if (obj == null) return null; 
        System.Reflection.MethodInfo inst = obj.GetType().GetMethod("MemberwiseClone", 
         System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); 
        if (inst != null) 
         return (T)inst.Invoke(obj, null); 
        else 
         return null; 
    } 
    
+3

No puedo entender por qué MemberwiseClone no es público ... ¡Y el "truco" de arriba es muy útil! ¡Pulgares hacia arriba! – Shaamaan

+0

En Silverlight, obtuve 'System.MethodAccessException no fue manejado por el código de usuario: Mensaje = Intento por el método 'ExtensionStaticClass.MemberwiseCloneEx (System .__ Canon)' para acceder al método 'System.Object.MemberwiseClone()' failed' –

+0

En Silverlight no se puede usar la reflexión a miembros privados para seguridad, limitado por microsoft, puede usar la serialización WCF para el clon – ModMa

0

aquí es un método de extensión que permite la clonación de cualquier objeto (el uso con la advertencia de que no funciona en todos los casos)

public static class Extra_Objects_ExtensionMethods 
{ 
    public static T clone<T>(this T objectToClone) 
    { 
     try 
     { 
      if (objectToClone.isNull()) 
       "[object<T>.clone] provided object was null (type = {0})".error(typeof(T)); 
      else 
       return (T)objectToClone.invoke("MemberwiseClone"); 
     } 
     catch(Exception ex) 
     { 
      "[object<T>.clone]Faild to clone object {0} of type {1}".error(objectToClone.str(), typeof(T)); 
     } 
     return default(T); 
    } 
} 
Cuestiones relacionadas