1

How to copy all from one list of object to another one. Both objects are with the same structure but with different name.

Here is the code:

 class Program
{
    static void Main(string[] args)
    {
        List<Test> lstTest = new List<Test>();
        List<Test2> lstTest2 = new List<Test2>();

        lstTest.Add(new Test { Name = "j", Score = 2 });
        lstTest.Add(new Test { Name = "p", Score = 3 });

        lstTest2 = lstTest.ConvertAll(x => (Test)x);

    }
}

class Test
{
    private string name;
    private int score;

    public string Name
    {
        get { return name;  }
        set { this.name = value; }
    }

    public int Score
    {
        get { return score; }
        set { this.score = value; }
    }
}

class Test2
{
    private string name;
    private int score;

    public string Name
    {
        get { return name; }
        set { this.name = value; }
    }

    public int Score
    {
        get { return score; }
        set { this.score = value; }
    }
}

Error that I get is

Cannot implicitly convert type System.Collections.Generic.List<Test> to System.Collections.Generic.List<cTest2>

Gilad Green
  • 36,708
  • 7
  • 61
  • 95
Josef
  • 2,648
  • 5
  • 37
  • 73
  • 2
    Possible duplicate of [Automapper copy List to List](https://stackoverflow.com/questions/8899444/automapper-copy-list-to-list) – mjwills Mar 26 '19 at 12:08
  • Have you checked https://stackoverflow.com/questions/222598/how-do-i-clone-a-generic-list-in-c ? – Amir Hajiha Mar 26 '19 at 12:09
  • Automapper is good solution but I'm not allowed to use it :( – Josef Mar 26 '19 at 12:15
  • 1
    The 2 classes are identical, in a real-world scenario a common base class or interface would be the best approach, imo – Daniel Mar 26 '19 at 12:23
  • @mjwills no, there are no hidden requirements. I heard for Automapper just right now and saw what is about and seems like a good solution but unfortunately I can't use it in my code. – Josef Mar 26 '19 at 12:54
  • Why can't you use it in your code? Perhaps you could mention what you are and are not allowed to use in your question? – mjwills Mar 26 '19 at 12:55
  • 1
    @Josef there is no magic stick, you either do it manually or do it using some auto mapping tools. and with your current provided example in question it should be easy, but if you say you have complex stuff and you can't use it, than what is your expectation to a solution? – Maytham Fahmi Mar 26 '19 at 13:05
  • Your options are 1. Write code to do it. 2. Let a lib like automapper do it 3. auto-generate code to do it. You seem to have rejected option #2. In option #1, have you thought of simply adding what I would call a `copy constructor`. And have you thought of some T4 template w.r.t option #3? Do you have any control over modifying `Test` and `Test2`? – Vikhram Mar 26 '19 at 13:24

3 Answers3

3

If you do not want to use automapper or other mapping tools, you can do this like this using select and new instance then return a list:

lstTest2 = lstTest.Select(e => new Test2()
{
    Score = e.Score,
    Name = e.Name
}).ToList();

In case of Automapper you can do something like:

var config = new MapperConfiguration(cfg => {

    cfg.CreateMap<Test, Test2>();
});
IMapper iMapper = config.CreateMapper();
lstTest2 = iMapper.Map<List<Test>, List<Test2>>(lstTest);

in config you define the type conversion. The map it from one to the other type.

You can of course extend your implementation to make it generic.

Documentation reference:

Maytham Fahmi
  • 31,138
  • 14
  • 118
  • 137
  • This seems nice solution but what if I have much more objects, variables inside object? – Josef Mar 26 '19 at 12:20
  • 3
    therefore Automapper or expressmapper is among other solutions to help with complex stuff. I can provide example of automapper or expressmapper for this example if you like – Maytham Fahmi Mar 26 '19 at 12:20
2

You are trying to convert implicitly Test to Test2 objects. A simple way to correct your code is to construct Test2 objects:

lstTest2 = lstTest.ConvertAll(x => new Test2 { Name = x.Name, Score = x.Score });

Even if the underlying structure is identical, you cannot cast from Test to Test2. If you want to cast explicitly, you have to define a cast operator:

class Test2 {
    // all code of class Test2

    public static explicit operator Test2(Test v)
    {
        return new Test2 { Name = v.Name, Score = v.Score };
    }
}

Then you can cast in ConvertAll:

lstTest2 = lstTest.ConvertAll(x => (Test2)x);
Bentoy13
  • 4,886
  • 1
  • 20
  • 33
  • This is good solution but I have many many properties and variables insde my real project. – Josef Mar 26 '19 at 12:47
-2

Instead of having two completely different objects with different names, study how to do object inheritance.

class Program
{
    static void Main(string[] args)
    {
        List<TestBase> lstTest = new List<TestBase>();

        lstTest.Add(new Test { Name = "j", Score = 2 });
        lstTest.Add(new Test2 { Name = "p", Score = 3 });
    }
}

class TestBase
{
    private string name;
    private int score;

    public string Name
    {
        get { return name;  }
        set { this.name = value; }
    }

    public int Score
    {
        get { return score; }
        set { this.score = value; }
    }
}

class Test : TestBase { }

class Test2 : TestBase { }
Patrick
  • 419
  • 4
  • 16