0

i have a simple query. Method-1 works well. But i don't understand what is wrong with method-2?

//method-1

        List<string> li = new List<string>();
        List<string> liSNB = new List<string>();
        li.Add("result1");
        li.Add("result2");
        li.Add("result3");
        var vQuery = from ssoli in li.AsEnumerable()
                     where li.Contains(ssoli)
                     where ssoli.Contains("2")
                     select new
                     {
                         soName = ssoli,
                     };

        liSNB.Clear();
        foreach (var v in vQuery)
            liSNB.Add(v.soName);
        li.Clear();
        li.AddRange(liSNB);
        lbxLinq.Items.AddRange(li.ToArray());//add results2

//method-2

        List<string> liSNB = new List<string>();
        liSNB.Add("result1");
        liSNB.Add("result2");
        liSNB.Add("result3");
        var vQuery = from ssoli in liSNB.AsEnumerable()
                     where liSNB.Contains(ssoli)
                     where ssoli.Contains("2")
                     select new
                     {
                         soName = ssoli,
                     };

        liSNB.Clear();
        foreach (var v in vQuery)
            liSNB.Add(v.soName);
        lbxLinq.Items.AddRange(liSNB.ToArray());//add nothing WHY???

Why no results in method-2 why? I have been workind for 2 days on just this situation. Is it bug or something? Thank you for answers initially.

2
  • 1
    Have you heard of LINQ's deferred execution? liSNB.Clear(); clears the list which also will "clear" the not executed query. You could persist it via ToList. Commented Sep 16, 2014 at 9:38
  • no i have'nt heard yet. is it about this error? Commented Sep 16, 2014 at 9:40

3 Answers 3

1

Since the linq uses deferred execution,your query is actualy executing in here:

foreach (var v in vQuery)

In your second code snippet you are removing all the items from liSNB before executing the query.So it doesn't return anything.

Btw this doesn't make any little sense, you can remove it:

where liSNB.Contains(ssoli)

You can read more about deferred execution in here and here

Sign up to request clarification or add additional context in comments.

Comments

1

I'll run over some mistakes in your second code block; most of them apply to the first block too.

    List<string> liSNB = new List<string>();
    liSNB.Add("result1");
    liSNB.Add("result2");
    liSNB.Add("result3");

The AsEnumerable in this line achieves nothing:

    var vQuery = from ssoli in liSNB.AsEnumerable()

This Contains check achieves nothing - of course ssoli is in the list or it wouldn't show up in the query:

                 where liSNB.Contains(ssoli)

This is fine:

                 where ssoli.Contains("2")

There's no reason to nest the string you want here - just select ssoli would work:

                 select new
                 {
                     soName = ssoli,
                 };

The query has not run yet - it is deferred. By clearing the list here, you have nothing to query over:

    liSNB.Clear();

While you are in the foreach loop the query is "running". By altering the source list while the query is running, you will cause the query to throw an exception. (You'd also need to remove soName. here if you stopped selecting it above):

    foreach (var v in vQuery)
        liSNB.Add(v.soName);

(Actually in your example you only have one matching item so you get away with it. If you had two or more items matching the query you'd be in trouble).

The ToArray is pointless here: I stand corrected, the method takes an object[].

    lbxLinq.Items.AddRange(liSNB.ToArray());

1 Comment

thank you for your helps but lbxLinq.Items.AddRange(liSNB.ToArray()); is necessary because lbxLinq is a ListBox
0

Linq query executes when the result is accessed, so you need to call ToArray() or ToList() after query:

var vQuery = (from ssoli in liSNB.AsEnumerable()
              where liSNB.Contains(ssoli) // this line is pointless because you are checking in same list
              where ssoli.Contains("2")
              select new
              {
                soName = ssoli,
              }).ToList();

Now your query will get executed when ToList() is called and result will be in vQuery.

The line where liSNB.Contains(ssoli) is not needed because you checking the source list item in the source list, so all items will be filtered, means no filtering will apply.

3 Comments

It's worth mentioning that where liSNB.Contains(ssoli) is pointless since it's checking for every string in the list, if it's in the list.
As is the AsEnumerable. As is selecting things from a list, building a list of the results, clearing the original list, copying everything from the results list to the original list, and then copying everything from the original list to a final list. Add ToList to the end of the query is very rarely a satisfactory answer.
in a fact i use a lot of queries like that so where liSNB.Contains(ssoli) is necessary for me. You are pretty right for this code but i' ve shorten my code for this question. Ehsan' s answers is working now for me. Thank you

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.