C# 比较不可为null的'int'和'null'(LINQ)

C# 比较不可为null的'int'和'null'(LINQ),c#,entity-framework,linq-to-sql,nullable,C#,Entity Framework,Linq To Sql,Nullable,我有EF模型类,我决定用一个bool属性扩展该类: 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; } }

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

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; }
}
然后我编写了一个方法,它将返回
a
集合和其他
C
集合,其中包含一个C映射(在现实世界的示例中,它包含一些
SystemId
,linq查询将由两列连接),并返回
a_DTO
集合:

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
    }
内部IQueryable MyMethod()=>
从dbContext.a中的
在dbContext.A_c_映射中加入c
在a.Id上等于c.a_Id到g
来自gg.DefaultIfEmpty()中的cc
选择一个新的DTO
{
Id=a.Id,
值=a.值,

BoolProp=cc.A_Id!=null/如果cc.A_Id永远不会变为null,并且您希望设置BoolProp的值,则可以通过将选择更改为以下值来删除警告:

select new A_DTO
{
    Id = a.Id,
    Value = a.Value,
    BoolProp = true
}

值类型
将始终有一个默认值(将它们声明为
可空
时例外),即使它们未初始化,即使您使用的是通过
LINQ
。因此
a_ID
将始终有一个值,
BoolProp
将始终为真

另一方面,
引用类型
将默认为
NULL

,根据,以下代码段是等效的:

List<C> list = new List<C>() { }; // empty list
List<C> listDefault = list.DefaultIfEmpty().ToList();
将引发NullReferenceException,因为cc为null

最后,条件似乎应该是:

BoolProp = cc != null
此外,这里还有一个通过单元测试演示差异的小示例:

    [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
                    };
[TestMethod]
public void TestMethod_DefaultifEmpty()
{
ListA=新列表()
{
新的A{Id=1,Value=“111”},
新的A{Id=2,Value=“222”},
};
ListC=新列表()
{
新的C{Id=1,A_Id=1}
};
AreEqual(2,MyMethod().Count());
}
公共列表列表a{get;set;}
公共列表ListC{get;set;}
公共IEnumerable MyMethod()=>
来自ListA的一家公司
在ListC中加入c
在a.Id上等于c.a_Id到g
来自g.DefaultIfEmpty()中的cc
选择一个新的DTO
{
Id=a.Id,
值=a.值,
//BoolProp=cc.A_Id!=null
BoolProp=cc!=null//替换为前一行以查看差异
};

上面说的是警告消息,但事实上我也得到了
false
值。我用
C
的实现编辑了我的问题,
A\u Id
不可为空。我现在复制了警告,让我检查一下。因为您的整个表达式都转换为SQL查询,而不是真正由.NET framework执行-这就是警告没关系,所以你可以禁用它(当然是针对这一行)。@Evk yeap,我知道,谢谢你的回答,我只是想确定这样做的方法是正确的。你自己看到这是一个错误的警告-那么禁用它会有什么错?@Evk有时不一定是“错(?)做点什么就有“更可取的”方法。@GertArnold正如我之前所说,在现实生活中,有两列左外连接,例如
C
table存储了一些
SystemId
A\u Id
,所以你可以得到哪个
A\u Id
属于你的系统。事实上
BoolProp=cc.A\u Id!=null
没有抛出任何异常,但是de>BoolProp=cc!=null有道理,所以我认为这样做会更准确。谢谢。
BoolProp = cc != null
    [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
                    };