SUMIT CHATTERJEE
SUMIT CHATTERJEE

Reputation: 23

Why changes to the outer data-source is not reflected, while they show-up for the inner data-source?

Why changes to the outer data-source is not reflected, while they show-up for the inner data-source?? Pls help

public static void MyMethod(char[] inputDS1, char[] inputDS2)
{
    Console.WriteLine("\n'from' clause - Display all possible combinations of a-b-c-d.");

    //query syntax
    IEnumerable<ChrPair> resultset = from res1 in inputDS1
                                     from res2 in inputDS2
                                     select new ChrPair(res1, res2);

    //Write result-set
    Console.WriteLine("\n\nOutput list -->");
    displayList(resultset);

    //swap positions
    //obs: changes to the first ds is not reflected in the resultset.
    char[] temp = inputDS1;
    inputDS1 = inputDS2;
    inputDS2 = temp;

    //run query again
    displayList(resultset);
    Console.WriteLine("\n------------------------------------------");
}

Input:

('a','b'), ('c','d')

Output:

ac, ad, bc, bd, **aa. ab, ba, bb**

I expected all possible combinations (ac, ad, bc, bd, ca, cb, da, db) as I swapped the Data-sources before the second Write. When I do a ToList() before the second Write, I get the expected result, so is it because that Select is lazy? Please explain.

Update

What I tried was - to add a ToList() (to force immediate execution) to the query-expression after the ds-swap. And I got the proper results - ac, ad, bc, bd, ca, cb, da, db. This would return expected results.

//query syntax
IEnumerable<ChrPair> resultset = from res1 in inputDS1
                                from res2 in inputDS2
                                select new ChrPair(res1, res2);

//Write result-set
Console.WriteLine("\n\nOutput list -->");
displayList(resultset);

//swap positions
//obs: changes to the first ds is not reflected in the resultset.
char[] temp = inputDS1;
inputDS1 = inputDS2;
inputDS2 = temp;

resultset = (from res1 in inputDS1
            from res2 in inputDS2
            select new ChrPair(res1, res2)).ToList();

//run query again
displayList(resultset);

Upvotes: 2

Views: 662

Answers (3)

Hamlet Hakobyan
Hamlet Hakobyan

Reputation: 33381

I think, the issue is that the first variable (inputDS1) don't included in any anonymous function (lambda) then the compiler wouldn't generate closure for it.

Compiler translates query to something like this:

IEnumerable<ChrPair> resultset = 
    inputDS1.SelectMany(c => inputDS2.Select(c1 => new ChrPair(c, c1)));

As you see, the inputDS1is not contains in any anonymous(lambda). Instead, the inputDS2 contains in lambda then compiler will generate for it closure. Therefore, in your second execution of query you have access to modified closure inputDS2.

Upvotes: 1

No Idea For Name
No Idea For Name

Reputation: 11597

what you got were combination from chars from inputDS1 with chars from inputDS2. this is what the query

    IEnumerable<ChrPair> resultset = from res1 in inputDS1
                                     from res2 in inputDS2
                                     select new ChrPair(res1, res2);

does, that's what you asked from it: "take 1 item from inputDS1 and 1 item from inputDS2 and combine the two to new ChrPair"

EDIT

after understanding your question let me explain something very fundamental:

the line

    IEnumerable<ChrPair> resultset = from res1 in inputDS1
                                     from res2 in inputDS2
                                     select new ChrPair(res1, res2);

does not return a list or IEnumerable<ChrPair>. it return a method that has a source (inputDS1) and an input. when you're swapping the two, you mess with the input of the method, but the source does not changed (it probably copied and not just referenced). when you do .ToList(); you activate the method, thus not getting any unexpected behavior due to commands called afterwards.

Upvotes: 1

sekky
sekky

Reputation: 834

From what I can see, the part

char[] temp = inputDS1;
    inputDS1 = inputDS2;
    inputDS2 = temp;

swaps around the input parameter and not the results you get from your linq statement.

Upvotes: -1

Related Questions