11

是否可以克隆一个对象,当它已知是一个装箱的 ValueType 时,而不编写特定于类型的克隆代码?

一些代码供参考

List<ValueType> values = new List<ValueType> {3, DateTime.Now, 23.4M};
DuplicateLastItem(values);

我遇到的特殊问题是基于值堆栈的虚拟指令机。(而且我懒得写 typeof(int) typeof(DateTime)....)

更新我想我把自己(和其他一些人)弄糊涂了。我的工作解决方案是;

List<ValueType> values = new List<ValueType> { 3, DateTime.Now, 23.4M }; 

// Clone
values.Add(values[values.Count() - 1]);

// Overwrite original
values[2] = 'p';

foreach (ValueType val in values)
   Console.WriteLine(val.ToString());
4

7 回答 7

6

您可以使用 hack 使用Convert.ChangeType

object x = 1;
var type = x.GetType();
var clone = Convert.ChangeType(x, type);

// Make sure it works
Assert.AreNotSame(x, clone);

结果是新对象中的值的副本。

于 2009-11-26T14:25:06.660 回答
5

根据定义,值类型的每个分配都是一个克隆。

编辑:

对值类型进行装箱时,值类型的副本将包含在 ReferenceType 的实例中。

根据克隆方法的不同,我预计不会有任何差异。

于 2009-11-26T14:05:57.900 回答
3

为什么还需要克隆代码?无论如何,值类型通常应该是不可变的,并且这不会被装箱改变。因此,设计良好的值类型不需要克隆。

于 2009-11-26T14:20:12.567 回答
3

我不知道,如果我完全误解了这个问题。
你想这样做吗?

public static void Main()
{
    List<ValueType> values = new List<ValueType> {3, DateTime.Now, 23.4M};
    DuplicateLastItem(values);

    Console.WriteLine(values[2]);
    Console.WriteLine(values[3]);
    values[3] = 20;
    Console.WriteLine(values[2]);
    Console.WriteLine(values[3]);
}

static void DuplicateLastItem(List<ValueType> values2)
{
    values2.Add(values2[values2.Count - 1]);
}
于 2009-11-26T14:51:56.307 回答
2
    private static T CloneUnboxed<T>(object o) where T : struct
    {
        return (T)o;
    }

    private static object CloneBoxed<T>(object o) where T : struct
    {
        return (object)(T)o;
    }

尽管我确实质疑两者的必要性,但考虑到值类型应该是不可变的。

于 2009-11-26T14:13:04.360 回答
2

回答标题而不是意图(如果有人发现这个问题),是的,通过RuntimeHelpers.GetObjectValue支持按值克隆装箱值类型。对于引用类型,此方法只返回原始引用,但对于值类型,它创建一个具有相同值的新装箱对象。对于不可变值类型,这不是必需的,因为不应修改实例,但对于可变类型,如果您将实例传递给可以修改它的代码,则使用它是安全的。

于 2019-12-17T12:20:37.093 回答
1

如果您要将对象转换为 ValueType,那不会导致进行克隆吗?然后可以重新装箱:

int i = 3;
object b = i; // box it
ValueType c = (ValueType) b; // unbox it
object d = c; // box it, effectively creating a clone

所以,我想我会说一种有效的克隆方法是:

object clone = (ValueType) boxed;
于 2009-11-26T14:18:39.077 回答