我想克隆一个通用对象并保留其类型。
run.Append(style.Clone(BlackFont)); //run object accepts only RunProperties objects
public T Clone(T what) {
if (what is RunProperties)
return (T) what.Clone();
}
它不起作用,因为T类型没有克隆方法,如何在第一个语句中不进行强制转换就可以解决这个问题。
run.Append((RunProperties) style.Clone(BlackFont)); //I do not want this
//not that this will work since you can't convert T to RunProperties
感谢您的帮助。
--- --- EDIT
在这种情况下,我似乎不会使用泛型。我会拆分数据。
答案 0 :(得分:3)
您始终可以将方法限制为仅接受实现ICloneable接口的类型:
public T Clone(T what) where T : ICloneable
{
if (what is RunProperties)
return (T) what.Clone();
}
但由于您的方法实际上只适用于一种类型,因此您可以稍微更改它并使用as
运算符:
public T Clone(T what)
{
var castWhat = what as RunProperties;
if(castWhat != null)
return castWhat.Clone();
}
答案 1 :(得分:2)
这是我编写的一个函数,它使用反射克隆类型为T的记录。 这是一个非常简单的实现,我没有处理复杂类型等。
public static T Clone<T>(T original)
{
T newObject = (T)Activator.CreateInstance(original.GetType());
foreach (var originalProp in original.GetType().GetProperties())
{
originalProp.SetValue(newObject, originalProp.GetValue(original));
}
return newObject;
}
我希望这可以帮助别人。
答案 2 :(得分:1)
您可以使用generic constraint将T类型约束为实现ICloneable的类型。
答案 3 :(得分:1)
你几乎自己给出了答案:
T type does not have a Clone method
另外,如果你只针对一种类型做某事,那么泛型方法有什么意义呢?
Clone方法来自ICloneable接口,因此您可以实现通用的Clone方法,使其适用于所有实现ICloneable
的类型:
public T Clone<T>(T what) where T: ICloneable
{
return (T) what.Clone();
}
答案 4 :(得分:0)
您可以使用通用约束:
public T Clone<T>(T what) where T: ICloneable
{
if (what is RunProperties)
return (T)what.Clone();
...
}
或者如果在包含类上定义了T generic参数:
public class Foo<T> where T: ICloneable
{
public T Clone(T what)
{
if (what is RunProperties)
return (T)what.Clone();
...
}
}
答案 5 :(得分:0)
我建议定义一个接口ISelf&lt; out T&gt;,带有一个名为“Self”的只读属性,类型为T(在任何实现中,应返回“this”)。他们定义ICloneable&lt; out T&gt;继承了ISelf&lt; T&gt;并实现一个类型为T的方法Clone(。
然后,如果你有一个方法需要从类型Foo派生并且可以克隆的方法,那么只需将该方法传递给ICloneable&lt; Foo&gt;。要将传入的对象用作“Foo”,请访问其“Self”属性。我建议使用公共克隆方法的类通常应该被密封,但只需添加一个公共的“克隆”包装器来扩展未密封的类型。这将允许存在或不允许克隆的派生类型。
考虑类家族Foo,CloneableFoo,DerivedFoo和CloneableDerivedFoo以及OtherDerivedFoo。
鉴于这些关系,一种方法接受Foo的任何可克隆衍生物将是有用的,而另一种方法将接受DerivedFoo的任何衍生物 - 可克隆或非克隆。第一种方法应使用ICloneable&lt; Foo&gt;类型的参数,而后者采用DerivedFoo类型的参数。请注意,如果DerivedFoo是从CloneableFoo而不是Foo派生的,那么在不承诺使用公共克隆方法的情况下,不可能从DerivedFoo派生任何东西。
答案 6 :(得分:0)
使用我开发的FastDeepcloner https://www.nuget.org/packages/FastDeepCloner/
/// <summary>
/// Clone Object, se FastDeepCloner for more information
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="items"></param>
/// <param name="fieldType"></param>
/// <returns></returns>
public static List<T> Clone<T>(this List<T> items, FieldType fieldType = FieldType.PropertyInfo)
{
return DeepCloner.Clone(items, new FastDeepClonerSettings()
{
FieldType = fieldType,
OnCreateInstance = new Extensions.CreateInstance(FormatterServices.GetUninitializedObject)
});
}