select 子句 (C# 參考)
在查詢運算式中,select
子句指定將在執行查詢時產生之值的類型。 結果是根據評估所有先前子句以及 select
子句本身中的任何運算式而來。 查詢運算式必須以 select
子句或 group 子句來終止。
下列範例示範查詢運算式中的簡單 select
子句。
class SelectSample1
{
static void Main()
{
//Create the data source
List<int> Scores = [97, 92, 81, 60];
// Create the query.
IEnumerable<int> queryHighScores =
from score in Scores
where score > 80
select score;
// Execute the query.
foreach (int i in queryHighScores)
{
Console.Write(i + " ");
}
}
}
//Output: 97 92 81
select
子句所產生的序列類型可決定查詢變數 queryHighScores
的類型。 在最簡單的情況下,select
子句只會指定範圍變數。 這會導致傳回的序列將相同類型的項目包含為資料來源。 如需詳細資訊,請參閱 LINQ 查詢作業中的類型關聯性。 不過,select
子句也提供功能強大的機制,將來源資料轉換 (或「投影」) 為新的類型。 如需詳細資訊,請參閱使用 LINQ 轉換資料 (C#)。
範例
下列範例示範 select
子句可接受的所有不同形式。 在每個查詢中,請注意 select
子句與「查詢變數」類型之間的關聯性 (studentQuery1
、studentQuery2
,依此類推)。
class SelectSample2
{
// Define some classes
public class Student
{
public required string First { get; init; }
public required string Last { get; init; }
public required int ID { get; init; }
public required List<int> Scores;
public ContactInfo? GetContactInfo(SelectSample2 app, int id)
{
ContactInfo? cInfo =
(from ci in app.contactList
where ci.ID == id
select ci)
.FirstOrDefault();
return cInfo;
}
public override string ToString() => $"{First} {Last}:{ID}";
}
public class ContactInfo
{
public required int ID { get; init; }
public required string Email { get; init; }
public required string Phone { get; init; }
public override string ToString() => $"{Email},{Phone}";
}
public class ScoreInfo
{
public double Average { get; init; }
public int ID { get; init; }
}
// The primary data source
List<Student> students =
[
new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= new List<int>() {97, 92, 81, 60}},
new Student {First="Claire", Last="O'Donnell", ID=112, Scores= new List<int>() {75, 84, 91, 39}},
new Student {First="Sven", Last="Mortensen", ID=113, Scores= new List<int>() {88, 94, 65, 91}},
new Student {First="Cesar", Last="Garcia", ID=114, Scores= new List<int>() {97, 89, 85, 82}},
];
// Separate data source for contact info.
List<ContactInfo> contactList =
[
new ContactInfo {ID=111, Email="SvetlanO@Contoso.com", Phone="206-555-0108"},
new ContactInfo {ID=112, Email="ClaireO@Contoso.com", Phone="206-555-0298"},
new ContactInfo {ID=113, Email="SvenMort@Contoso.com", Phone="206-555-1130"},
new ContactInfo {ID=114, Email="CesarGar@Contoso.com", Phone="206-555-0521"}
];
static void Main(string[] args)
{
SelectSample2 app = new SelectSample2();
// Produce a filtered sequence of unmodified Students.
IEnumerable<Student> studentQuery1 =
from student in app.students
where student.ID > 111
select student;
Console.WriteLine("Query1: select range_variable");
foreach (Student s in studentQuery1)
{
Console.WriteLine(s.ToString());
}
// Produce a filtered sequence of elements that contain
// only one property of each Student.
IEnumerable<String> studentQuery2 =
from student in app.students
where student.ID > 111
select student.Last;
Console.WriteLine("\r\n studentQuery2: select range_variable.Property");
foreach (string s in studentQuery2)
{
Console.WriteLine(s);
}
// Produce a filtered sequence of objects created by
// a method call on each Student.
IEnumerable<ContactInfo> studentQuery3 =
from student in app.students
where student.ID > 111
select student.GetContactInfo(app, student.ID);
Console.WriteLine("\r\n studentQuery3: select range_variable.Method");
foreach (ContactInfo ci in studentQuery3)
{
Console.WriteLine(ci.ToString());
}
// Produce a filtered sequence of ints from
// the internal array inside each Student.
IEnumerable<int> studentQuery4 =
from student in app.students
where student.ID > 111
select student.Scores[0];
Console.WriteLine("\r\n studentQuery4: select range_variable[index]");
foreach (int i in studentQuery4)
{
Console.WriteLine("First score = {0}", i);
}
// Produce a filtered sequence of doubles
// that are the result of an expression.
IEnumerable<double> studentQuery5 =
from student in app.students
where student.ID > 111
select student.Scores[0] * 1.1;
Console.WriteLine("\r\n studentQuery5: select expression");
foreach (double d in studentQuery5)
{
Console.WriteLine("Adjusted first score = {0}", d);
}
// Produce a filtered sequence of doubles that are
// the result of a method call.
IEnumerable<double> studentQuery6 =
from student in app.students
where student.ID > 111
select student.Scores.Average();
Console.WriteLine("\r\n studentQuery6: select expression2");
foreach (double d in studentQuery6)
{
Console.WriteLine("Average = {0}", d);
}
// Produce a filtered sequence of anonymous types
// that contain only two properties from each Student.
var studentQuery7 =
from student in app.students
where student.ID > 111
select new { student.First, student.Last };
Console.WriteLine("\r\n studentQuery7: select new anonymous type");
foreach (var item in studentQuery7)
{
Console.WriteLine("{0}, {1}", item.Last, item.First);
}
// Produce a filtered sequence of named objects that contain
// a method return value and a property from each Student.
// Use named types if you need to pass the query variable
// across a method boundary.
IEnumerable<ScoreInfo> studentQuery8 =
from student in app.students
where student.ID > 111
select new ScoreInfo
{
Average = student.Scores.Average(),
ID = student.ID
};
Console.WriteLine("\r\n studentQuery8: select new named type");
foreach (ScoreInfo si in studentQuery8)
{
Console.WriteLine("ID = {0}, Average = {1}", si.ID, si.Average);
}
// Produce a filtered sequence of students who appear on a contact list
// and whose average is greater than 85.
IEnumerable<ContactInfo> studentQuery9 =
from student in app.students
where student.Scores.Average() > 85
join ci in app.contactList on student.ID equals ci.ID
select ci;
Console.WriteLine("\r\n studentQuery9: select result of join clause");
foreach (ContactInfo ci in studentQuery9)
{
Console.WriteLine("ID = {0}, Email = {1}", ci.ID, ci.Email);
}
}
}
/* Output
Query1: select range_variable
Claire O'Donnell:112
Sven Mortensen:113
Cesar Garcia:114
studentQuery2: select range_variable.Property
O'Donnell
Mortensen
Garcia
studentQuery3: select range_variable.Method
ClaireO@Contoso.com,206-555-0298
SvenMort@Contoso.com,206-555-1130
CesarGar@Contoso.com,206-555-0521
studentQuery4: select range_variable[index]
First score = 75
First score = 88
First score = 97
studentQuery5: select expression
Adjusted first score = 82.5
Adjusted first score = 96.8
Adjusted first score = 106.7
studentQuery6: select expression2
Average = 72.25
Average = 84.5
Average = 88.25
studentQuery7: select new anonymous type
O'Donnell, Claire
Mortensen, Sven
Garcia, Cesar
studentQuery8: select new named type
ID = 112, Average = 72.25
ID = 113, Average = 84.5
ID = 114, Average = 88.25
studentQuery9: select result of join clause
ID = 114, Email = CesarGar@Contoso.com
*/
如前一個範例中的 studentQuery8
所示,您有時可能想要所傳回序列的項目只包含來源項目的屬性子集。 盡量保持最少的所傳回序列,以降低記憶體需求,並提高查詢的執行速度。 做法是在 select
子句中建立匿名型別,並使用物件初始設定式以利用來源項目中的適當屬性來初始化它。 如需如何執行此作業的範例,請參閱物件和集合初始設定式。
備註
在編譯時間,select
子句會轉譯為 Select 標準查詢運算子的方法呼叫。