Linq查询不会从另一个对象内的对象返回结果

时间:2018-12-03 17:24:57

标签: c# linq

我正在尝试使用Linq返回对象内对象的属性。这是演示行为的程序的简化版本。

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp2
{
    class Program
    {
        public class Associate
        {
            public string AssocType { get; set; }
            public Contact contact { get; set; }
            public Associate(string assocType)
            {
                AssocType = assocType;
                //contact = new Contact("Contact 1", 1234);
                //contact2 = new Contact("Contact 2", 23456);
            }
        }
        public class Contact
        {
            string v1;
            int v2;
            public Contact(string v1, int v2) { this.v1 = v1; this.v2 = v2; }
            public string Name { get; set; }
            public int ID { get; set; }
        }

        static void Main(string[] args)
        {
            Associate assoc1 = new Associate("Type1");
            assoc1.contact = new Contact("Contact 1", 9876);
            Associate assoc2 = new Associate("Type2");
            assoc2.contact = new Contact("Contact 2", 1234);
            List<Associate> aList = new List<Associate>
            {
                assoc1,assoc2
            };
            var contactname = aList
                .Where(s => s.AssocType == "Type1")
                .Select(s => s.contact.Name)
                .FirstOrDefault();
            Console.Write(contactname);
            Console.Read();

        }
    }
}

contactname变量作为null出现,但应以字符串形式返回Contact 1。我已经在调试器中检查了所有对象的设置正确并具有适当的值。我在做什么错了?

我还尝试了下面的linq语法(代替var contact name = aList...部分,但我认为它是不正确的,因为由于Type inference failed而无法编译。

        var name = from Associate in aList
                   from Contact in Associate
                   where Associate.AssocType == "Type1"
                   select Contact.Name;

2 个答案:

答案 0 :(得分:3)

在您的Contact类中,您永远不会设置Name属性,因此当您执行以下管道时:

var contactname = aList.Where(s => s.AssocType == "Type1")
                       .Select(s => s.contact.Name)
                       .FirstOrDefault();

它返回null(不要与null返回的FirstOrDefault混淆,这是null属性的Name值,因为它从来没有设置)。

您可以通过以下方式证明这一点:

var count = aList.Count(s => s.AssocType == "Type1" && s.contact.Name == null);
Console.Write(count); // prints  --> 1

所以,您的意思是:

var contactname = aList.Where(s => s.AssocType == "Type1")
                       .Select(s => s.contact.v1) // note the change
                       .FirstOrDefault();

假设v1是公开的。

否则您将明确需要在上述管道之前的某个时间填充Name对象的Contact属性。


最后,为了完整性,如果要查询语法,请执行以下操作:

var result = (from a in aList
              where a.AssocType == "Type1"
              select a.contact.Name)
             .FirstOrDefault();

答案 1 :(得分:0)

联系人姓名为null,因为您尚未在任何地方进行初始化。

  

公共联系人(字符串v1,整数v2){this.v1 = v1; this.v2 = v2; }

这应该是

public Contact(string v1, int v2) { Name = v1; ID = v2; }

  

公共字符串名称{组; }

这应该是(也与ID相同)

public string Name { get { return v1; } }