【问题标题】:Cannot access protected member 'object.MemberwiseClone()'无法访问受保护的成员“object.MemberwiseClone()”
【发布时间】:2011-01-02 15:39:39
【问题描述】:

我正在尝试在我的自定义类上使用 .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)

这是什么意思?或者更好的是,我如何克隆 Enemy 类?

【问题讨论】:

    标签: c# clone


    【解决方案1】:

    在任何类X 中,您只能在X 的实例上调用MemberwiseClone(或任何其他受保护的方法)。 (或者从X派生的类)

    由于您尝试克隆的 Enemy 类没有继承您尝试克隆的 GameBase 类,因此您会收到此错误。

    要解决此问题,请将公共 Clone 方法添加到 Enemy,如下所示:

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

    【讨论】:

    • 但我认为 MemberwiseClone 是 Object 的一种方法,afaik 所有的类都是从它派生的?
    • 是的,但是你不能调用其他类的受保护方法,除非它继承自 you。否则,您只需从该类继承即可调用任何类上的任何受保护成员(包括MemberwiseClone)。这将使protected 几乎毫无用处。
    • "protected" 是另一种说法:只有类本身知道何时 MemberwiseClone() 是正确的做法。它很少是,谷歌“深拷贝”。
    • ICloneable 在 Silverlight 5.0 中不可用
    • @PeterLee:你不需要使用ICloneable
    【解决方案2】:
    • 不能直接使用 MemberwiseClone(),必须通过派生类实现(推荐)
    • 但是,通过反射,你可以欺骗它:)
    • 你可以对没有实现 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;
      }
      

    【讨论】:

    • 我不明白为什么MemberwiseClone 不公开......而且上面的“作弊”非常有用!竖起大拇指!
    • 在 Silverlight 中,我得到了System.MethodAccessException was unhandled by user code: Message=Attempt by method 'ExtensionStaticClass.MemberwiseCloneEx&lt;System.__Canon&gt;(System.__Canon)' to access method 'System.Object.MemberwiseClone()' failed
    • 在Silverlight中不能使用对私有成员的反射来保证安全,受微软限制,可以使用WCF序列化进行克隆
    • @Shaamaan:它不是公开的,因为由类所有者决定克隆应该如何工作;逐位克隆任意类不一定是安全的。例如,Thread 实例的按位克隆意味着什么?
    • 这个作弊方法效果很好,但要注意使用反射对性能的影响。如果您要完成数千个(甚至更多)克隆操作,我不建议您使用此功能
    【解决方案3】:

    这是一个允许克隆任何对象的扩展方法(请注意它并非在所有情况下都有效)

    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);
        }   
    }
    

    【讨论】:

      猜你喜欢
      • 2015-01-30
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 2013-11-30
      • 2014-01-26
      • 2014-02-22
      • 2015-12-30
      • 2022-01-06
      相关资源
      最近更新 更多