In your case, I would say "lose T " - you are not using anything important that cannot be done in other ways ( Activator.CreateInstance , for example). You could offer two APIs - one universal, one not common to provide convenient casting. For instance:
BusinessObject newObj = (BusinessObject)Activator.CreateInstance(obj.GetType());
This is also very important, because the T you want is not really an ad T , and specific T Meaning: if you have SuperCustomer : Customer , but put it in the Customer variable and then call Clone , you want a new SuperCustomer . T , however, will be Customer . Using GetType() would be much more reliable.
Another useful trick here is dynamic , which is a hidden way of throwing from non-generic to generic. Consider:
dynamic foo = 123; Bar(foo); void Bar<T>(T bar) { Console.WriteLine(typeof(T)); }
will write System.Int32 . He flipped over to the correct T "on the fly," despite the fact that he really knew about the object in the compiler ( dynamic is implemented mainly as an object with some fancy bits).
However, to emphasize - I would not use this here: I would simply have:
public static BusinessObject Clone(this BusinessObject obj) { BusinessObject newObj = (BusinessObject) Activator.CreateInstance(obj.GetType()); var props = newObj.Properties; foreach (var p in props) newObj.Properties[p.Name].SetValue(newObj, obj.Properties[p.Name].GetValue(obj)); return newObj; }
with dynamic as my backup strategy if I really need generics.
source share