views:

138

answers:

3

I have 2 instances of a class that implements the IEnumerable interface. I would like to create a new object and combine both of them into one. I understand I can use the for..each to do this.

Is there a linq/lambda expression way of doing this?

EDIT

public class Messages : IEnumerable, IEnumerable<Message>
{
  private List<Message> message = new List<Message>();

  //Other methods
}

Code to combine

MessagesCombined messagesCombined = new MessagesCombined();

MessagesFirst messagesFirst = GetMessageFirst();
MessagesSecond messagesSecond = GetMessageSecond();

messagesCombined = (Messages)messagesFirst.Concat(messagesSecond); //Throws runtime exception

//Exception is

Unable to cast object of type '<ConcatIterator>d__71`1[Blah.Message]' to type 'Blah.Messages'.
+2  A: 

Try something like this:

var combined = firstSequence.Concat(secondSequence);

This is using the Enumerable.Concat extension method.

Andrew Hare
Concat doesn't seem to work. Please see edit
DotnetDude
Why are you creating custom classes for set of messages? Just use `IEnumerable<Message>` for all 3. The problem you are having is that you are trying to assign `Messages` to an instance of something more derived, which is not allowed.
NickLarsen
>> Why are you creating custom classes for set of messages?I am working with existing types. I am not the author of Messages and Message class.
DotnetDude
+1  A: 

You will want to use Concat.

Pet[] cats = GetCats();
Pet[] dogs = GetDogs();

IEnumerable<Pet> query = cats.Concat(dogs);

Per your edit:

IEnumerable<Message> messagesCombined;

MessagesFirst messagesFirst = GetMessageFirst();
MessagesSecond messagesSecond = GetMessageSecond();

// if this doesn't work, you can cast both MessagesFirst and MessagesSecond to IEnumerable<Message>
messagesCombined = messagesFirst.Concat(messagesSecond);
NickLarsen
+1  A: 

The Enumarable.Concat method returns an IEnumerable<Message> (or in fact an <ConcatIterator>d__71<Message> as the exception message shows). You can not cast that to your Messages type. You can do the following:

var m = new Messages(messagesFirst.Concat(messagesSecond));

And make sure your Messages type has a constructor taking an IEnumerable<Message>:

public class Messages : IEnumerable, IEnumerable<Message>
{
    private List<Message> message;

    public Message(IEnumerable<Message> messages)
    {
        this.message = new List<Message>(messages);
    }

    //Other methods
}
Steven
@Steven - I need the result to be of type Messages. var wouldn't work for me.
DotnetDude
Well, it is of type Messages. "var" just instructs the compiler to "guess" the most correct type according to what's on the right side of the statement; in this case, the creation of a Messages object.It's called "type inference", and it's really useful.
Etienne de Martel
@Smith - So, if the combining logic is in a method with return param of Messages, can I return a object of type "var" without the compiler complaining or any exceptions at runtime? Also, I do further processing of the combined list, so at some point i have to cast it to Messages.
DotnetDude
From MSDN: "Beginning in Visual C# 3.0, variables that are declared at method scope can have an implicit type var. An implicitly typed local variable is strongly typed just as if you had declared the type yourself, but the compiler determines the type." If I write"var i = 2;", then i will be of type int, because 2 is of type int. See here: http://msdn.microsoft.com/en-us/library/bb383973.aspx
Etienne de Martel
@Smith - Thanks for the explanation. I do understand that the type of var is the type that is inferred from the right side of the equation. However, the issue i have is that I cannot return an object of type var from the method with return type of Members.
DotnetDude
@DotnetDude: There is no such thing as a `var` object type. As Smith tries to explain, the C# compiler just fils in the correct type for you. If your method returns `Messages`, then you can return `m`, because `m` will be of type `Messages` (in my example that is).
Steven