0
\$\begingroup\$

Recently I was in need of a method to copy an object and pass it to a method which alters the data. Since a class is passed by reference this would alter the class in the caller which I don't want.

So, I wrote a generic extension method which does the trick. Yet i'm unsure if this is a good solution to my problem. I would like to use reflection to achieve the goal. I can't use ICloneable and I would like to avoid serializing and deserializing the class. I have also looked into making the class a struct but will refrain from this since the classes can be way larger than 16 bytes and don't really suit the basic guidelines of when to use a struct.

Here is my extension method:

public static T CreateNonReferencedObject<T>(this T obj)
{
    var tObj = (T)Activator.CreateInstance(typeof(T));

    if (obj == null) return tObj;

    var properties = obj.GetType().GetProperties();

    foreach (var property in properties)
    {
        var value = property.GetValue(obj);
        tObj.GetType().GetProperty(property.Name).SetValue(tObj, value);
    }

    return tObj;
}
\$\endgroup\$
6
  • 2
    \$\begingroup\$ First need to make sure to only get properties that are writable before calling SetValue. Second issue is that if any of the properties are objects (like List<string>), then you will only be copying the reference. This would need to be recursive to solve that. serializing /deserializing would require less lines than the fixes needed, but there are number of ways to attack this. \$\endgroup\$
    – Greg M
    Commented Mar 23, 2023 at 14:33
  • \$\begingroup\$ That is a valid point, I haven't thought of recursion inside the object passed to the method. Although for now I am only passing classes where there are direct properties it would be better to future proof it \$\endgroup\$
    – Roe
    Commented Mar 23, 2023 at 14:38
  • \$\begingroup\$ Since a class is passed by reference -> Objects are passed passed, not a class. Then, C# is pass by value, by default. For pass by reference use the ref keyword in a method signature. \$\endgroup\$
    – radarbob
    Commented Mar 25, 2023 at 21:13
  • \$\begingroup\$ A C# struct is a value type, so there is no reference to a struct. ... RE: "16 bytes". I know that's quoted from microsoft, but how in the wide world of compilation can I know what my High Level Language will compile to without trial and error? If this nugget of esoteric 4-bit CPU nostalgia is about taking up stack memory, the computer will let me know if there is StackOverflow. Hey, moderators! I'm supposed to get 15 points for using "StackOverflow", validly, in a sentence. \$\endgroup\$
    – radarbob
    Commented Mar 25, 2023 at 21:27
  • 1
    \$\begingroup\$ When solving one's own question it is perfectly acceptable to post that solution and select the answer. \$\endgroup\$
    – radarbob
    Commented Mar 26, 2023 at 18:02

1 Answer 1

2
\$\begingroup\$

After a deeper dive as to why I exactly made this function I have found out that I made this extension method to remove the reference from an entity I Get() with Entityframework facepalm. I have rewritten the code to .AsNoTracking() instead so the code actually makes sense. The CreateNonReferencedObject() method is now unnecessary.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.