如何在同一个 LINQ 查询中使用 `let` 关键字和 select ValueTuple?
How to use `let` keyword and select ValueTuple in the same LINQ query?
理想情况下,我想用 let
关键字定义一些临时变量,以不重复相同的 Contains
方法调用,用这些值计算一些其他内容,然后 return ValueTuple
。这可能在一个链式或查询表达式中吗?到目前为止,我只用 2 个表达式来处理它。哦,collection当然是IEnumerable
。
using System;
using System.Collections.Generic;
using System.Linq;
namespace FeaturesTest
{
class Program
{
class Song
{
public string Artist { get; set; }
public string Name { get; set; }
}
class User
{
public List<Song> FavouriteSongs { get; set; }
public List<Song> HatedSongs { get; set; }
}
static void Main( string[] args )
{
List<Song> allSongs = new List<Song>
{
new Song{ Artist = "Atheist", Name = "Enthralled in Essence" },
new Song{ Artist = "Death", Name = "Jealosy" },
new Song{ Artist = "Cynic", Name = "Evolutionary Sleeper" },
new Song{ Artist = "Ghost", Name = "Square Hammer" },
};
User bob = new User
{
FavouriteSongs = new List<Song>
{
allSongs[0],
allSongs[1]
},
HatedSongs = new List<Song>
{
allSongs[3],
}
};
var objects = from song in allSongs
let isFavourite = bob.FavouriteSongs.Contains( song )
let isHated = bob.HatedSongs.Contains( song )
select new
{
Artist = song.Artist,
Name = song.Name,
IsFavourite = isFavourite,
IsHated = isHated,
IsNeutral = !isFavourite && !isHated
};
var tuples = objects.Select( o => (Artist: o.Artist,
Name: o.Name,
IsFavourite: o.IsFavourite,
IsHated: o.IsHated,
IsNeutral: o.IsNeutral) );
Console.WriteLine( "Artist Name Is Favourite Is Hated Is Neutral" );
Console.WriteLine( "------ ---- ------------ -------- ----------" );
foreach( (string Artist, string Name, bool IsFavourite, bool IsHated, bool IsNeutral) in tuples )
{
Console.WriteLine( $"{Artist,-10} {Name,-25} {IsFavourite,-15} {IsHated,-10} {IsNeutral}" );
}
}
}
}
除非我遗漏了什么:是的 - 只需投影一个 NamedTuple 而不是一个匿名对象:
var objects = from song in allSongs
let isFavourite = bob.FavouriteSongs.Contains( song )
let isHated = bob.HatedSongs.Contains( song )
select (
song.Artist,
song.Name,
isFavourite,
isHated,
IsNeutral : !isFavourite && !isHated
);
此外,至于您的 foreach
循环 - 您已经给出了名称,只需使用 var
(我认为它更容易阅读):
foreach( var t in tuples )
{
Console.WriteLine( $"{t.Artist,-10} {t.Name,-25} {t.IsFavourite,-15} {t.IsHated,-10} {t.IsNeutral}" );
}
你的 Contains
也很脆弱。它将通过引用而不是内容来比较对象。在当前的示例中,它没问题,但如果对象是具有相同内容的不同实例,它就无法工作。要更正该工具 Equals
和 GetHashCode
.
理想情况下,我想用 let
关键字定义一些临时变量,以不重复相同的 Contains
方法调用,用这些值计算一些其他内容,然后 return ValueTuple
。这可能在一个链式或查询表达式中吗?到目前为止,我只用 2 个表达式来处理它。哦,collection当然是IEnumerable
。
using System;
using System.Collections.Generic;
using System.Linq;
namespace FeaturesTest
{
class Program
{
class Song
{
public string Artist { get; set; }
public string Name { get; set; }
}
class User
{
public List<Song> FavouriteSongs { get; set; }
public List<Song> HatedSongs { get; set; }
}
static void Main( string[] args )
{
List<Song> allSongs = new List<Song>
{
new Song{ Artist = "Atheist", Name = "Enthralled in Essence" },
new Song{ Artist = "Death", Name = "Jealosy" },
new Song{ Artist = "Cynic", Name = "Evolutionary Sleeper" },
new Song{ Artist = "Ghost", Name = "Square Hammer" },
};
User bob = new User
{
FavouriteSongs = new List<Song>
{
allSongs[0],
allSongs[1]
},
HatedSongs = new List<Song>
{
allSongs[3],
}
};
var objects = from song in allSongs
let isFavourite = bob.FavouriteSongs.Contains( song )
let isHated = bob.HatedSongs.Contains( song )
select new
{
Artist = song.Artist,
Name = song.Name,
IsFavourite = isFavourite,
IsHated = isHated,
IsNeutral = !isFavourite && !isHated
};
var tuples = objects.Select( o => (Artist: o.Artist,
Name: o.Name,
IsFavourite: o.IsFavourite,
IsHated: o.IsHated,
IsNeutral: o.IsNeutral) );
Console.WriteLine( "Artist Name Is Favourite Is Hated Is Neutral" );
Console.WriteLine( "------ ---- ------------ -------- ----------" );
foreach( (string Artist, string Name, bool IsFavourite, bool IsHated, bool IsNeutral) in tuples )
{
Console.WriteLine( $"{Artist,-10} {Name,-25} {IsFavourite,-15} {IsHated,-10} {IsNeutral}" );
}
}
}
}
除非我遗漏了什么:是的 - 只需投影一个 NamedTuple 而不是一个匿名对象:
var objects = from song in allSongs
let isFavourite = bob.FavouriteSongs.Contains( song )
let isHated = bob.HatedSongs.Contains( song )
select (
song.Artist,
song.Name,
isFavourite,
isHated,
IsNeutral : !isFavourite && !isHated
);
此外,至于您的 foreach
循环 - 您已经给出了名称,只需使用 var
(我认为它更容易阅读):
foreach( var t in tuples )
{
Console.WriteLine( $"{t.Artist,-10} {t.Name,-25} {t.IsFavourite,-15} {t.IsHated,-10} {t.IsNeutral}" );
}
你的 Contains
也很脆弱。它将通过引用而不是内容来比较对象。在当前的示例中,它没问题,但如果对象是具有相同内容的不同实例,它就无法工作。要更正该工具 Equals
和 GetHashCode
.