Tag Archives: class

Dynamically copy a class from one instance to another using reflection

Occasionally, you find that you want to copy a class to another instance of itself. There are various reason, but typically the code can result in a `CopyTo()` function, with a long list of properties to be copied across. There’s nothing wrong with that and, performance-wise, it’s probably faster than what I’m suggesting in this post.

Here’s a generic method that will copy the class for you:

        private static void CopyClass<T>(T copyFrom, T copyTo)
        {
            if (copyFrom == null || copyTo == null)
                throw new Exception("Must not specify null parameters");

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

            foreach (var p in properties.Where(prop => prop.CanRead && prop.CanWrite))
            {
                object copyValue = p.GetValue(copyFrom);
                p.SetValue(copyTo, copyValue);
            }
        }

Nothing too onerous if you’ve ever seen reflection, but let’s quickly run through it. The first thing it does is ensure that both to destination and source are provided, then it gets a list of properties that can be read and written to, and copies the value across.

Obviously, this won’t include any private properties.

Here’s some test / example code for it. First, the class to copy:

    class TestClass
    {
        public string teststring { get; set; }

        public string mynextstring { get; set; }

        public void test()
        {

        }

        public int get1 { get { return 1; } }

        //public TestClass2 testClass2 { get; set; }
    }

And then tha calling code:

            TestClass tc = new TestClass()
            {
                //testClass2 = new TestClass2(),
                teststring = "test2123",
                mynextstring = "31"

            };

            var t = new TestClass();
            CopyClass<TestClass>(tc, t);
            Console.WriteLine(t.teststring);
            Console.WriteLine(t.mynextstring);
            //Console.WriteLine(t.testClass2.teststring);

            Console.ReadLine();

Okay, so that works; however, you’ll notice that I’ve included and commented out an external class reference. If you include this, then it will copy the class reference (not the class). What if we want to use this to copy child classes?

Actually, it’s not too complicated:

        private static void CopyClass<T>(T copyFrom, T copyTo, bool copyChildren)
        {
            if (copyFrom == null || copyTo == null)
                throw new Exception("Must not specify null parameters");

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

            foreach (var p in properties.Where(prop => prop.CanRead && prop.CanWrite))
            {
                if (p.PropertyType.IsClass && p.PropertyType != typeof(string))
                {
                    if (!copyChildren) continue;

                    var destinationClass = Activator.CreateInstance(p.PropertyType);
                    object copyValue = p.GetValue(copyFrom);

                    CopyClass(copyValue, destinationClass, copyChildren);

                    p.SetValue(copyTo, destinationClass);                  
                }
                else
                {
                    object copyValue = p.GetValue(copyFrom);
                    p.SetValue(copyTo, copyValue);
                }
            }
        }

There’s a couple of things to note here: firstly, we need to check if the value is a class, but exclude strings as a special case (I couldn’t find a neater way of doing this); secondly, create the destination class using reflection and cache the source value. Finally, we just recursively call the function, using generic type inference in order to supply the type (which we don’t have as a generic at this point).

If you now just uncomment out the references to TestClass2 it should recursively copy the class.

I have to be honest and say that I’m not too happy with the check for a string type, but other than that, this is quite a neat little way to copy a class.

Assigning an index to a collection using LINQ

This is a neat little trick that I came across when looking for a way to arbitrarily assign a unique index to each element in a collection. Imagine a scenario where you have a collection of a class such as the following:

    class TestIndex
    {
        public string Title { get; set; }
        public int Amount { get; set; }
        public int Index { get;set; }

        public override string ToString()
        {
            return string.Format("{0}: {1}, {2}", Index, Title, Amount);
        }

    }

Here’s the code to populate it:

List<TestIndex> l = new List<TestIndex>()
{
    new TestIndex() { Title="test1", Amount=20 },
    new TestIndex() { Title="test2", Amount=30 },
    new TestIndex() { Title="test3", Amount=5 },
    new TestIndex() { Title="test4", Amount=30 }
};

I’ve overriden ToString so that we can see what’s in it:

foreach (var t in l)
{
    Console.WriteLine(t.ToString());
}

linq1

A you can see, we have a field called Index, but it contains nothing (well, 0). However, it can be populated in a single line:

var newList = l.Select((el, idx) => { el.Index = idx; return el; });

linq2

The Select statement has an override that will tell you the index of that element based on the order; for example:

var newList = l.OrderBy(a => a.Amount).Select((el, idx) => { el.Index = idx; return el; });

linq3

Complete Code Listing

    class Program
    {
        static void Main(string[] args)
        {
            List<TestIndex> l = new List<TestIndex>()
            {
                new TestIndex() { Title="test1", Amount=20 },
                new TestIndex() { Title="test2", Amount=30 },
                new TestIndex() { Title="test3", Amount=5 },
                new TestIndex() { Title="test4", Amount=30 }
            };

            foreach (var t in l)
            {
                Console.WriteLine(t.ToString());
            }

            Console.WriteLine(" - - - ");

            var newList = l.Select((el, idx) => { el.Index = idx; return el; });

            foreach (var t in newList)
            {
                Console.WriteLine(t.ToString());
            }

            Console.ReadLine();
        }

        
    }

    class TestIndex
    {
        public string Title { get; set; }
        public int Amount { get; set; }
        public int Index { get;set; }

        public override string ToString()
        {
            return string.Format("{0}: {1}, {2}", Index, Title, Amount);
        }
    }

Cannot modify members of ‘myVar’ because it is a ‘foreach iteration variable’

This can occur in a situation such as the following:

        private struct Position
        {
            public int left;
            public int top;
        }

        private static List<Position> _points = new List<Position>();

        private static void MyFunc()
        {
            foreach (Position pnt in _points)
            {
                pnt.top++;
            }
        }

This will fail to compile with the error message:

Cannot modify members of ‘pnt’ because it is a ‘foreach iteration variable’

Why?

The reason for this is simply that you cannot modify the collection that you iterate through, as you iterate through it. From the above statement, I can see that modifying the variable `top` would make no difference, but imagine this:

            foreach (Position pnt in _points.OrderBy(p => p.top))
            {
                pnt.top++;
            }

How to fix?

There’s two easy ways around this; the first is to switch a struct for a class:

    internal class Position
    {
        public int left;
        public int top;
    }

That would now work. The reason for this is the way that the two types are stored. Classes are reference types; which means that what is actually stored in the collection is a list of pointers to classes, and not the classes themselves; consequently, changing them does not affect the actual collection. You can even use orderby on the collection because it caches the order at the start of the loop (I’m certainly not advocating actually doing this).

What if you need to use a struct

Structs are immutable; which means you cannot change them. You can do something like this; although I personally can’t see why it’s easier that using a class:

            for (int i = 0; i <= _points.Count() - 1; i++)
            {
                _points[i] = new Position() { left = _points[i].left, top = _points[i].top + 1 };
            }