比较不可为空的int和null(LINQ) [英] Comparing non nullable `int` to `null` (LINQ)

查看:59
本文介绍了比较不可为空的int和null(LINQ)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有EF模型类,并且我决定用一个 bool 属性扩展该类:

  A类{public int ID {get;放;}公共字符串值{get;放;}}A_DTO类别:A{公共布尔BoolProp {get;放;}}C级{public int ID {get;放;}public int A_Id {get;放;}} 

然后我编写了一个方法,该方法将返回与其他一些 C 集合连接的 A 集合,其中包含 A <=> C 映射(嗯,实际上这个世界示例包含一些 SystemId ,并且linq查询将由两列组成)并返回 A_DTO 集合:

 内部IQueryable< A_DTO>MyMethod()=>从dbContext.A中的在dbContext.A_C_Mapping中加入c在a.Id上等于c.A_Id到g从gg中的cc.DefaultIfEmpty()选择新的A_DTO{ID = a.Id,值= a.值,BoolProp = cc.A_Id!= null//<-永远是正确的,那么,警告消息是什么} 

( dbContext 是我的EF上下文对象)

当然,由于 cc.A_Id 不是可为空的 int ,警告消息将出现,表示

"表达式的结果将始终为 'true' 因为 int 类型的值永远不会等于 null 值类型为 int?"

这是正确的,但实际上我得到的结果是完全正确的,因为在 C 集合中缺少映射时,我的左外部联接返回了 null .

所以问题是:这样做是否正确并保持原样,还是我需要以另一种方式实施?

解决方案

根据

I have EF model class and I've decided to extend that class with one bool property:

class A 
{
    public int Id { get; set; }
    public string Value { get; set; }
}

class A_DTO : A
{
    public bool BoolProp { get; set; }
}


class C
{
    public int Id { get; set; }
    public int A_Id { get; set; }
}

Then I wrote a method, which will return that A collection joined with some other C collection, which contains A <=> C mapping (well, in real world example it contains some SystemId and linq query will be joined by 2 columns) and returns A_DTO collection:

internal IQueryable<A_DTO> MyMethod() => 
    from a in dbContext.A
    join c in dbContext.A_C_Mapping
    on a.Id equals c.A_Id into g
    from cc in gg.DefaultIfEmpty()
    select new A_DTO
    {
        Id = a.Id,
        Value = a.Value,
        BoolProp = cc.A_Id != null //<- will be always true, well, that what says warning message
    }

(dbContext is my EF context object)

and of course because of cc.A_Id is not a nullable int the warning message will appear, saying that

"The result of expression will be always 'true' since the value of type int is never equal to null value of type int?"

which is true, but in fact I get results perfectly correct, because of my left outer join return nulls when mapping missing in C collection.

So the question: is it correct approach to do so and leave it as it is, or I need to implement it another way?

解决方案

According to the DefaultIfEmpty method definition, the following code snippets are equivalent:

List<C> list = new List<C>() { }; // empty list
List<C> listDefault = list.DefaultIfEmpty().ToList();

and

List<C> listDefault = new List<C>() { null }; // Since default(C) is null

Thus when you use g.DefaultIfEmpty() you will get a unique cc object which is null, consequently the line:

BoolProp = cc.A_Id != null

will throw a NullReferenceException because cc is null.

At the end it seems that the condition should be:

BoolProp = cc != null

Besides here is a small example which demonstrates the difference through a unit test:

    [TestMethod]
    public void TestMethod_DefaultifEmpty()
    {
        ListA = new List<A>()
        {
            new A { Id=1, Value="111" },
            new A { Id=2, Value="222" },
        };
        ListC = new List<C>()
        {
            new C { Id=1,  A_Id=1 }
        };

        Assert.AreEqual(2, MyMethod().Count());
    }

    public List<A> ListA { get;  set; }
    public List<C> ListC { get; set; }
    public IEnumerable<A_DTO> MyMethod() =>
                    from a in ListA
                    join c in ListC
                    on a.Id equals c.A_Id into g
                    from cc in g.DefaultIfEmpty()
                    select new A_DTO
                    {
                        Id = a.Id,
                        Value = a.Value,
                        //BoolProp = cc.A_Id != null
                        BoolProp = cc != null // replace by previous line to see the difference
                    };

这篇关于比较不可为空的int和null(LINQ)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆