LINQ查詢運算式 - Select、Cast、OfType
一、查詢運算式結構
linq syntax
各部分的查詢運算式為
範圍變數:該變數位置在from後面的變數,在某方面不算是一種變數,他只能用在查詢運算式上,
主要是存放目前所擷取到的元素資料,並可用來提供其他查詢運算式使用。
基本的查詢運算式為
var query = from user in SampleData.AllUsers select user.Name;
其作用相等於
var query = SampleData.AllUsers.Select(user => user.Name);
二、Select
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
SampleData data = new SampleData();
var query = from user in SampleData.AllUsers
select user;
foreach (var item in query)
{
Console.WriteLine(item);
}
}
}
public class SampleData
{
static List<User> users;
public static IEnumerable<User> AllUsers
{
get { return users; }
}
public static class Users
{
public static readonly User TesterTim = new User("Tim Trotter", UserType.Tester);
public static readonly User TesterTara = new User("Tara Tutu", UserType.Tester);
public static readonly User DeveloperDeborah = new User("Deborah Denton", UserType.Developer);
public static readonly User DeveloperDarren = new User("Darren Dahlia", UserType.Developer);
public static readonly User ManagerMary = new User("Mary Malcop", UserType.Manager);
public static readonly User CustomerColin = new User("Colin Carton", UserType.Customer);
}
public SampleData()
{
users = new List<User>
{
Users.TesterTim,
Users.TesterTara,
Users.DeveloperDeborah,
Users.DeveloperDarren,
Users.ManagerMary,
Users.CustomerColin
};
}
}
public class User
{
public string Name { get; set; }
public UserType UserType { get; set; }
public User(string name, UserType userType)
{
Name = name;
UserType = userType;
}
public override string ToString()
{
return string.Format("User: {0} ({1})", Name, UserType);
}
}
public enum UserType : byte
{
Customer,
Developer,
Tester,
Manager,
}
}
執行結果為
Select 通常又稱為投影 projection,
可以透過他來將原始的型別轉換成新的型別,
如:從IEnumerable<SampleData.AllUser>的集合中,
選出 user.Name 並包裝成 lEnumerable<string> 集合回傳。
var query = from user in SampleData.AllUsers
select user.Name;
上例select方法只能取得單一屬性,如果想取多個屬性,
則可以包裝成物件,如下例為使用匿名型別(Anonymous Type)來重新建立匿名物件。
var query = from user in SampleData.AllUsers
select new
{
Name = user.Name,
Length = user.Name.Length
};
也可以直接使用投影出來的屬性來做成匿名物件
var query = from user in SampleData.AllUsers
select new { user.Name, user.Name.Length };
或是使用Tuple 類別
var query = from user in SampleData.AllUsers
select new Tuple<string, int>(user.Name, user.Name.Length);
另外一種表示法為使命名物件
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
SampleData data = new SampleData();
var query = from user in SampleData.AllUsers
select new NameLengrth { name = user.Name, Length = user.Name.Length };
foreach (var item in query)
{
Console.WriteLine(item);
}
}
}
class NameLengrth
{
public string name { get; set; }
public int Length { get; set; }
}
public class SampleData
{
//...
}
public class User
{
//...
}
public enum UserType : byte
{
//...
}
}
注意,NameLengrth是一個類別(class)
這種表示法也行
var query = from user in SampleData.AllUsers
select new NameLengrth() { name = user.Name, Length = user.Name.Length };
三、Cast、OfType
Cast 會將集合內所有元素轉換成目標型別,若有集合無法轉換的型別,
這時候會拋出 InvalidCastException 的例外;
Oftype 會將集合內所有元素依依轉換成目標型別,若有集合無法轉換的型別,
這時候會忽略。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;
namespace Linqtest
{
class Program
{
static void Main(string[] args)
{
ArrayList list = new ArrayList { "First","Second","Third"};
IEnumerable<string> strings = list.Cast<string>();
foreach (var item in strings)
{
Console.WriteLine(item);
}
list = new ArrayList { 1, "not a int", 2, 3 };
IEnumerable<int> ints = list.OfType<int>();
foreach (var item in ints)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
}
再看一個例子
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;
namespace Linqtest
{
class Program
{
static void Main(string[] args)
{
ArrayList list = new ArrayList { "First","Second","Third"};
var strings = from string entry in list
select entry;
foreach (var item in strings)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
}
使用明確型別的範圍變數時,編譯器會去呼叫 Cast 擴充方法,
以確保目前查詢運算式的來源資料是可以被轉換範圍變數的型別。
參考資料:
A Visual Explanation of SQL Joins
[C#.NET] 如果可以 請盡量使用LINQ查詢語法而不是使用迴圈