无法理解这个IEnumerable <t> .ToArray()示例</t>

时间:2011-07-02 21:04:11

标签: c# linq

在以下几行中,我确实理解LINQ部分,但当我尝试理解最后一行时,我完全麻木了。

var roles=from r in db.Role
               from u in db.User
               where r.RoleID==u.RoleID
               && u.UserName==username
               select new
                 {
                    RoleNames=r.RoleName
                 };
               return new string[] {roles.ToArray()[0].RoleNames};

变量roles的类型为IEnumerable(对吗?),它包含RoleNames个对象的匿名集合? 最后一行,复杂的字符串[] {roles.ToArray()[0].RoleNames}赋值 ,roles转换为数组(OK)然后幻像索引[0](为什么?)然后在RoleNames包含的最终roles匿名类型,但这一切如何变为一串字符串。
感谢先进,即使是外观。

4 个答案:

答案 0 :(得分:6)

很难从这段代码中说出来,但感觉这段代码并没有像作者那样做。

为什么用户有RoleID列?如果用户只能拥有一个角色,那就没问题。但是这段代码似乎意味着用户可以拥有多个角色。用户表是否包含每个用户的多个条目,每个用户分配一个角色?用户/角色通常是多对多的关系。

原作者正在获取该查询的结果,只是获取它的第一个结果(在这种情况下,调用roles.First()可能更合适),然后在那里取一个角色并返回它在数组中。如果这个数组只有一个元素,那就没问题但是感觉正确的男孩。如果作者追求多个角色,他们只会得到一个角色。更不用说如果没有找到任何角色,这段代码就会爆炸。

如果用户真的只能拥有一个角色,那么获得该角色的方式就会更简单(也更容易阅读)。也许是这样的:

var roles=from r in db.Role
           from u in db.User
           where r.RoleID==u.RoleID
           && u.UserName==username
           select r.RoleName;

 // at this point roles will probably have zero or one entry, so you can do
 return roles.FirstOrDefault(); // return the one role found as a string
     // or null if none were

 // or if you really do want the array
 return roles.ToArray(); // will return a string array,
     // possibly having 1 or 0 elements

答案 1 :(得分:2)

 return new string[] {roles.ToArray()[0].RoleNames};

ToArray()返回一个具有RoleNames属性的匿名类型的数组。然后,索引器[0]返回此数组的第一个元素,属性访问器.RoleNames最终返回其RoleNames属性。这只是一个字符串,但new string[] {..}使它成为一个包含单个元素的字符串数组。

答案 2 :(得分:2)

最后一行实现了对数组的查询,然后只获取数组的第一项,并从该项的RoleNames属性创建一个新的字符串数组。

更好的解决方案是获取RoleName属性的值,而不是使用包含它的属性创建新对象:

var roles =
  from r in db.Role
  from u in db.User
  where r.RoleID == u.RoleID && u.UserName == username
  select r.RoleName;

由于rolesIEnumerable<string>,您可以使用Take方法将结果限制为第一个字符串,然后您可以将其转换为数组;

return roles.Take(1).ToArray();

当您使用ToArray方法实现它之前限制结果时,它只需要读取第一个项目,而不是读取所有项目,然后扔掉除第一个项目之外的所有项目。

为什么单个字符串应该作为数组返回并不明显。如果这是一个错误,并且它应该动态返回所有角色名称,只需从代码中删除Take(1)

答案 3 :(得分:1)

我不相信它按预期工作。

它只返回第一场比赛的角色名称。

相反,代码应该是

var roles=(from r in db.Role
           from u in db.User
           where r.RoleID==u.RoleID
           && u.UserName==username
           select r.RoleName).ToArray();
return roles;
事实证明,这很接近于接受的答案中所描述的内容!

如果用户只能拥有一个角色,并且可以保证他们拥有有效的角色ID,并且调用代码需要一个数组,那么这段代码将按预期工作,但这并不是最直接的方式这样做。