无法访问受保护的成员“object.MemberwiseClone()”

Posted

技术标签:

【中文标题】无法访问受保护的成员“object.MemberwiseClone()”【英文标题】:Cannot access protected member '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 类?

【问题讨论】:

【参考方案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);
       

【讨论】:

以上是关于无法访问受保护的成员“object.MemberwiseClone()”的主要内容,如果未能解决你的问题,请参考以下文章

静态成员函数无法访问类的受保护成员

在派生类中无法访问受保护的成员

基类无法按预期访问受保护的成员

无法访问受保护的成员“object.MemberwiseClone()”

我无法访问我的基类的受保护成员

在派生类中无法访问受保护的成员?