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

32

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

3个回答

47

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

由于你正在尝试克隆的 Enemy 类没有继承你正在尝试克隆的 GameBase 类,所以你会遇到这个错误。

为了解决这个问题,请在 Enemy 中添加一个公共的 Clone 方法,就像这样:

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

3
我认为MemberwiseClone是Object的一个方法,据我所知,所有类都是从它派生出来的? - Xenoprimate
5
是的,但是除非一个类继承了你,否则你无法调用不同类的受保护方法。否则,你将能够在任何类上调用任何受保护成员(包括“MemberwiseClone”)。这将使“protected”几乎变得无用。 - SLaks
ICloneable 在 Silverlight 5.0 中不可用。 - Peter Lee
@PeterLee:你不需要使用ICloneable - SLaks
@SLaks,我明白了。但是似乎我们必须创建一个新类来继承内置类。我真正需要的是制作现有类实例的克隆,例如UIElement,请看我的问题:http://stackoverflow.com/questions/13522001/silverlight-how-to-make-a-shallowcopy-of-a-uielement - Peter Lee
显示剩余3条评论

38
  • you can´t use MemberwiseClone() directly, you must implement it via derived class (recomended)
  • but, via reflection, you can cheat it :)
  • you can use this litle extension for the classes that not implement 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;
    }
    

7
我不明白为什么MemberwiseClone不是公共的...而且上面的“技巧”非常有用!赞一个! - MBender
在Silverlight中,我得到了System.MethodAccessException was unhandled by user code: Message=Attempt by method 'ExtensionStaticClass.MemberwiseCloneEx<System.__Canon>(System.__Canon)' to access method 'System.Object.MemberwiseClone()' failed - Peter Lee
在Silverlight中,由于安全性的限制,无法使用反射访问私有成员。但是,可以使用WCF序列化来进行克隆操作。 - ModMa
2
@Shaamaan:这是因为它取决于类所有者确定克隆应该如何工作,任意类进行逐位克隆可能不安全。例如,对Thread实例进行按位克隆会有什么意义呢? - Asherah
这个作弊方法效果很好,但需要注意反射的使用会对性能产生影响。如果你需要进行成千上万甚至更多次克隆操作,我不建议使用这个函数。 - radomeit

-1
这里有一个扩展方法,允许克隆任何对象(使用时请注意,并非在所有情况下都有效)。
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);
    }   
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接