【问题标题】:LINQ - "Index was outside the bounds of the array."LINQ -“索引超出了数组的范围。”
【发布时间】:2016-10-31 21:17:14
【问题描述】:

我收到此错误:

“索引超出了数组的范围。”

通过使用此 LINQ 查询

我想,如果 A.LogOutTime 返回 null 然后显示“未知”。

var listItems = (from A in data orderby A.FirstName 
    select new {
        Action = "Logout", 
        UserName = A.FirstName + " " + A.SurName, 
        ID = A.Id, 
        AccessDate = (A.LogOutTime ?? "Unknown")
                       .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[0], 
        AccessTimeFrame = (A.LogOutTime ?? "Unknown")
                           .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[1] 
                       + " " + (A.LogOutTime ?? "Unknown")
                           .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[2], 
        Comment = "Never delete this Archive" 
 }).Distinct();

我该如何解决这个问题?

【问题讨论】:

  • 这与 LINQ 无关。检查您的数组,您在某些地方使用了错误的索引。也许,试图访问一个空数组上的项目?
  • 将其拆分为更易于管理的内容?乍一看,你有很多索引到数组中,这些索引不能保证有那么多项目(例如,如果为 null,你设置为“未知”,当拆分时,它将只有一个项目 - 尝试获取项目1 或 2 将因此异常而失败)。
  • 如果你在空间上拆分“Unkown”,你将得到一个只有一个值的数组。
  • 还有为什么LogOutTimestring 而不是DateTime
  • @AbhilashJA 不要。这是一个严重的错误。另存为datetime。即使您不想修复该错误,也可以解析日期字符串而不是拆分。您可以使用DateTime.DateDateTime.TimeOfDay 检索DateTime 的日期和时间部分

标签: c# linq


【解决方案1】:

问题在于,当A.LogOutTimenull 时,您将字符串"Unknown" 放置在之后由" " 拆分到返回的IEnumerable 的某些索引处。这些索引不存在,因此您会收到该错误。

我建议您执行以下操作:

  1. 使用let,这样您就不会每次都重复拆分。拆分时使用 C# 6.0 ?. 以避免NullReferenceException (如果LogOutTime 为空,sections 也仍为空)
  2. 分配给属性时,检查LogOutTime 是否为null,如果是,则分配"Unknown"。如果不是根据需要使用拆分的结果
  3. 使用ElementAtOrDefault(n),这样您就不会访问不存在的索引

所以:

var listItems = (from A in data 
                 orderby A.FirstName
                 let sections = A.LogOutTime?.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)            
                 select new { 
                     Action = "Logout", 
                     UserName = A.FirstName + " " + A.SurName, 
                     ID = A.Id, 
                     AccessDate = A.LogOutTime == null ? "Unknown" : sections.ElementAtOrDefault(0), 
                     AccessTimeFrame = A.LogOutTime == null ? "Unknown" : (sections.ElementAtOrDefault(1) + " " + 
                                       sections.ElementAtOrDefault(2)), 
                     Comment = "Never delete this Archive" }
                ).Distinct();

另外通过检查LogOutTime 不是null 我假设它是string。而是将其保存为DateTime,这样您就不会遇到拆分和访问某些不存在的索引的问题。使用DateTimeToString() 重载的不同属性,您可以在其中指定所需的格式。有关此事的更多信息:Custom Date and Time Format Strings

【讨论】:

    【解决方案2】:

    使用“let”关键字将注销时间的各个部分仅拆分一次。然后在计算 AccessTimeFrame 的同时检查部件的长度。

    var listItems = (from A in data
                        let logOutTimeParts = (A.LogOutTime ?? "Unknown").Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
                        orderby A.FirstName
                        select new
                        {
                            Action = "Logout",
                            UserName = A.FirstName + " " + A.SurName,
                            ID = A.Id,
                            AccessDate = logOutTimeParts[0],
                            AccessTimeFrame = logOutTimeParts.Length >= 3 ? logOutTimeParts[1] + " " + logOutTimeParts[2] : "",
                            Comment = "Never delete this Archive"
                        }
        ).Distinct();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-19
      • 1970-01-01
      • 2015-11-06
      相关资源
      最近更新 更多