解释使用变量和直接执行之间的区别

时间:2014-03-04 07:45:41

标签: c# lambda logic

enter image description here

上图是我ListN的示例数据。

我还有另一个列表ListA,其中有两个项目{ID=1090,ID=1089}

现在我有以下代码:

CODEa所

var x = 0;
foreach(var item in ListA){
    if(ListN.Where(x=>x.ID==item.ID).Any(y=>y.Data != null))
    {
        x = ListN.Where(x=>x.ID==item.ID).Min(y=>y.Data).Value;
        break;
    }
}

CodeB:

var x = 0;
foreach(var item in ListA){
    var list = ListN.Where(x=>x.ID==item.ID);
    if(list.Any(y=>y.Data != null))
    {
        x = list.Min(y=>y.Data).Value;
        break;
    }
}

有人可以向我解释为什么 CodeA 错误地抛出null异常,但 CodeB 正常工作?

3 个答案:

答案 0 :(得分:2)

不是问题的答案。但这是实现你想要做的事情的可怕方式......

var x = (from item in ListA
        join list in ListN on item.ID equals list.ID
        where list.Data != null
        select list.Data).Min();

你的意思更清楚了。此外,Linq编译器实际上会为您生成更优的代码(因为它将使用哈希查找)。

你遇到的主要问题是你试图将命令式编程(foreach,break等)与声明式编程(Where,Min等)混淆并让自己感到困惑。

答案 1 :(得分:1)

这是因为您在第一个If条件中测试了空值,但在第二个中您无视该测试并再次选择与Where子句匹配的项目。

您在第二个选择中没有获得与第一个测试中相同的列表。

CodeB示例中,您只处理绝对没有空数据字段的项目。

我建议做这样的事情:

var x = 0;
foreach(var item in ListA)
{
    var list = ListN.Where(x=> x.ID == item.ID && x.Data != null).ToList();

    if(list.Any())
    {
       x = list.Min(y=>y.Data).Value;
       break;
    }    
}

答案 2 :(得分:1)

这是的答案。但它太大了,无法发表评论。

我无法重现你的问题。我不知道这两个答案是什么声称在一个样本中发生某种形式的“更多过滤”而不是另一个样本。

这是您的代码,一些修正(因为您不能拥有var x并使用x作为lambda参数)和您的数据。它输出No Exception两次,表明两个代码示例运行良好:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;

namespace ConsoleApplication4
{
    class Program
    {
        class N
        {
            public int ID { get; set; }
            public int? Data { get; set; }
        }

        class A
        {
            public int ID { get; set; }
        }

        static int CodeA(List<N> ListN, List<A> ListA)
        {
            var c = 0;
            foreach (var item in ListA)
            {
                if (ListN.Where(x => x.ID == item.ID).Any(y => y.Data != null))
                {
                    c = ListN.Where(x => x.ID == item.ID).Min(y => y.Data).Value;
                    break;
                }
            }
            return c;
        }

        static int CodeB(List<N> ListN, List<A> ListA)
        {
            var c = 0;
            foreach (var item in ListA)
            {
                var list = ListN.Where(x => x.ID == item.ID);
                if (list.Any(y => y.Data != null))
                {
                    c = list.Min(y => y.Data).Value;
                    break;
                }
            }
            return c;
        }

        static void Main(string[] args)
        {
            var listN = new List<N>
            {
                new N {ID = 1090, Data = 1},
                new N {ID = 1090, Data = 3},
                new N {ID = 1090, Data = 4},
                new N {ID = 1089, Data = 1},
                new N {ID = 1089, Data = 3},
                new N {ID = 1089, Data = 4},
                new N {ID = 1089, Data = null}
            };
            var listA = new List<A>
            {
                new A {ID = 1089},
                new A {ID = 1090}
            };
            try
            {
                CodeA(listN, listA);
                Console.WriteLine("No Exception");
            }
            catch (Exception ex)
            {
                Console.WriteLine("A exception: " + ex.ToString());
            }
            try
            {
                CodeB(listN, listA);
                Console.WriteLine("No Exception");
            }
            catch (Exception ex)
            {
                Console.WriteLine("B exception: " + ex.ToString());
            }
            Console.ReadLine();
        }
    }

}

如果您希望获得有关实际问题的帮助,请参考上面的代码示例并对CodeA引发您所讨论的此异常以及CodeB没有引发异常的情况进行适当的更改。然后,您可以将其纳入您的问题,我将删除此“答案”。