Linq:根据变量分组结果不同(例如枚举)
Linq: Group by that groups results differently according to a variable (enum for example)
我正在尝试 运行 一个查询 其中 'GroupBy' 子句将根据说,一个将数据绑定到组合框等的枚举值对结果进行不同的分组.
我尝试使用 switch case 来做到这一点,但这导致了 'GroupBy' 子句上的编译器错误 CS0411,因为据我所知,从 lambda 返回的对象类型会有所不同,具体取决于在哪种情况下执行。
如何巧妙地实现这个功能?
我在下面附上了一个问题的最小示例,作为控制台程序。
class Program
{
static List<Person> People;
enum GroupBy
{
Month,
Year
}
static void Main(string[] args)
{
People = new List<Person>();
People.Add(new Person()
{
Dob = new DateTime(2000,10,1),
Name = "James",
IsSelected = false
});
People.Add(new Person()
{
Dob = new DateTime(2000, 5, 1),
Name = "Anne",
IsSelected = true
});
People.Add(new Person()
{
Dob = new DateTime(2000, 5, 23),
Name = "Bob",
IsSelected = true
});
People.Add(new Person()
{
Dob = new DateTime(1999, 1, 15),
Name = "Kate",
IsSelected = false
});
// Obviously, in the real thing, the grouping value would be
// databound to a combobox or something.
GroupBy grouping = GroupBy.Month;
var groups = People
.OrderBy(x => x.Dob)
.GroupBy(x => /* PROBLEM LINE - Gives compiler error CS0411 */
{
switch(grouping)
{
case GroupBy.Month:
return new { x.Dob.Year, x.Dob.Month };
case GroupBy.Year:
return new { x.Dob.Year};
default:
throw new Exception("No can do");
}
});
Console.WriteLine("Grouping is: " + grouping + "\r\n");
foreach(var group in groups)
{
Console.WriteLine("Group: " + group.Key);
foreach(Person p in group)
{
Console.WriteLine("\t" + p.Name + ", " + p.Dob);
}
Console.WriteLine("");
}
Console.ReadKey();
}
}
public class Person
{
public DateTime Dob { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
问题出现在返回匿名类型时的 switch 语句中。编译器无法推断类型(因为它是由编译器为每个单独的投影生成的)并因此抛出错误。
您可以通过创建包装器轻松解决此问题 class:
public class GroupedResult
{
public int Year { get; set; }
public int Month { get; set; }
}
var groups = People
.OrderBy(x => x.Dob)
.GroupBy(x => /* PROBLEM LINE - Gives compiler error CS0411 */
{
switch (grouping)
{
case GroupBy.Month:
return new GroupedResult { Year = x.Dob.Year, Month = x.Dob.Month };
case GroupBy.Year:
return new GroupedResult { Year = x.Dob.Year };
default:
throw new Exception("No can do");
}
});
OR 通过确保两个匿名类型上存在相同的属性,从而产生相同的 compiler-generated 类型:
var groups = People
.OrderBy(x => x.Dob)
.GroupBy(x => /* PROBLEM LINE - Gives compiler error CS0411 */
{
switch (grouping)
{
case GroupBy.Month:
return new { Year = x.Dob.Year, Month = x.Dob.Month };
case GroupBy.Year:
return new { Year = x.Dob.Year, Month = 0 };
default:
throw new Exception("No can do");
}
});
最简单的解决方案:
.GroupBy(x => new
{
Year = x.Dob.Year,
Month = grouping == GroupBy.Month ? x.Dob.Month : 0
};
Year
始终是您分组的一部分
只有当 grouping
等于 Month
时,Month
才会成为您分组的一部分
- 否则使用常量<<因此不分组
我建议避免在 GroupBy
委托中抛出异常。
- 宁愿做一个初步检查并提前退出。
我正在尝试 运行 一个查询 其中 'GroupBy' 子句将根据说,一个将数据绑定到组合框等的枚举值对结果进行不同的分组.
我尝试使用 switch case 来做到这一点,但这导致了 'GroupBy' 子句上的编译器错误 CS0411,因为据我所知,从 lambda 返回的对象类型会有所不同,具体取决于在哪种情况下执行。
如何巧妙地实现这个功能?
我在下面附上了一个问题的最小示例,作为控制台程序。
class Program
{
static List<Person> People;
enum GroupBy
{
Month,
Year
}
static void Main(string[] args)
{
People = new List<Person>();
People.Add(new Person()
{
Dob = new DateTime(2000,10,1),
Name = "James",
IsSelected = false
});
People.Add(new Person()
{
Dob = new DateTime(2000, 5, 1),
Name = "Anne",
IsSelected = true
});
People.Add(new Person()
{
Dob = new DateTime(2000, 5, 23),
Name = "Bob",
IsSelected = true
});
People.Add(new Person()
{
Dob = new DateTime(1999, 1, 15),
Name = "Kate",
IsSelected = false
});
// Obviously, in the real thing, the grouping value would be
// databound to a combobox or something.
GroupBy grouping = GroupBy.Month;
var groups = People
.OrderBy(x => x.Dob)
.GroupBy(x => /* PROBLEM LINE - Gives compiler error CS0411 */
{
switch(grouping)
{
case GroupBy.Month:
return new { x.Dob.Year, x.Dob.Month };
case GroupBy.Year:
return new { x.Dob.Year};
default:
throw new Exception("No can do");
}
});
Console.WriteLine("Grouping is: " + grouping + "\r\n");
foreach(var group in groups)
{
Console.WriteLine("Group: " + group.Key);
foreach(Person p in group)
{
Console.WriteLine("\t" + p.Name + ", " + p.Dob);
}
Console.WriteLine("");
}
Console.ReadKey();
}
}
public class Person
{
public DateTime Dob { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
问题出现在返回匿名类型时的 switch 语句中。编译器无法推断类型(因为它是由编译器为每个单独的投影生成的)并因此抛出错误。
您可以通过创建包装器轻松解决此问题 class:
public class GroupedResult
{
public int Year { get; set; }
public int Month { get; set; }
}
var groups = People
.OrderBy(x => x.Dob)
.GroupBy(x => /* PROBLEM LINE - Gives compiler error CS0411 */
{
switch (grouping)
{
case GroupBy.Month:
return new GroupedResult { Year = x.Dob.Year, Month = x.Dob.Month };
case GroupBy.Year:
return new GroupedResult { Year = x.Dob.Year };
default:
throw new Exception("No can do");
}
});
OR 通过确保两个匿名类型上存在相同的属性,从而产生相同的 compiler-generated 类型:
var groups = People
.OrderBy(x => x.Dob)
.GroupBy(x => /* PROBLEM LINE - Gives compiler error CS0411 */
{
switch (grouping)
{
case GroupBy.Month:
return new { Year = x.Dob.Year, Month = x.Dob.Month };
case GroupBy.Year:
return new { Year = x.Dob.Year, Month = 0 };
default:
throw new Exception("No can do");
}
});
最简单的解决方案:
.GroupBy(x => new
{
Year = x.Dob.Year,
Month = grouping == GroupBy.Month ? x.Dob.Month : 0
};
Year
始终是您分组的一部分
只有当 Month
才会成为您分组的一部分- 否则使用常量<<因此不分组
grouping
等于 Month
时,我建议避免在 GroupBy
委托中抛出异常。
- 宁愿做一个初步检查并提前退出。