LINQ解析:LINQ to Objects

可以查询的内容:不是所有的对象都可以使用LINQ to Objects查询,使用LINQ to Objects的首要条件是:需要查询的对象是实现了IEnumerable<T>接口的集合类型;说明:本篇中的例子兼顾使用查询表达式和查询操作符

1. 数组

包括元素类型为Object在内的所有类型的数组都可以使用LINQ to Objects,示例如下:

using System;
using System.Linq;

class ArrayTest
{
class Cutomer
{
public Cutomer(String name, String company, UInt16 age)
{
Name = name;
Company = company;
Age = age;
}

public string Name { get; set; }
public string Company { get; set; }

private ushort age;
public ushort Age
{
get { return age; }
set
{
if (value > 200 || value < 1)
throw new ArgumentOutOfRangeException("age", "Age must between 1 and 200!");

age = value;
}
}
}

static void Main()
{
Object[] array = { 's', "String", true, 28, 26.7, 27.6F, 18UL, new Cutomer("Steven Xue", "Google", 25) };

var types =
array
.Select(item => item.GetType().Name)
.OrderBy(type => type);

ObjectDumper.Write(types);
}
}

输出如下:

Boolean
Char
Cutomer
Double
Int32
Single
String
UInt64

以下示例是强类型的数组:

using System;
using System.Collections.Generic;
using System.Linq;

class TypedArrayTest
{
class Book
{
public String Isbn { get; set; }
public Int32 PageCount { get; set; }
public Decimal Price { get; set; }
public String Publisher { get; set; }
public String Title { get; set; }
public String[] Authors { get; set; }

public override String ToString()
{
return Title;
}
}

static void Main()
{
Book[] books = {
new Book { Title="LINQ in Action" },
new Book { Title="JavaScript in Action" },
new Book { Title="CLR Via C#" } 
};

var titles =
books
.Where(book => book.Title.Contains("LINQ"))
.Select(book => book.Title);

ObjectDumper.Write(titles);
}
}

输出如下:

LINQ in Action

说明:ObjectDumper是一个非常有用的辅助类,能够显示对象中的数据,随微软的LINQ示例代码提供(具体位置:VS安装目录\Samples \1033目录下的CSharpSamples.zip中提供了ObjectDumper辅助类);从上面的例子可以看出,查询能够应用在元素为自定义类 型的数组上,以上示例为Cutomer和Book类


2. 泛型列表

以下列出主要的泛型列表:

System.Collections.Generic.List<T>
System.Collections.Generic.LinkedList<T>
System.Collections.Generic.Queue<T>
System.Collections.Generic.Stack<T>
System.Collections.Generic.HashSet<T>
System.Collections.ObjectModel.Collection<T>
System.ComponentModel.BindingList<T>

示例如下:

using System;
using System.Collections.Generic;
using System.Linq;

class GenericListTest
{
class Book
{
public String Isbn { get; set; }
public Int32 PageCount { get; set; }
public Decimal Price { get; set; }
public String Publisher { get; set; }
public String Title { get; set; }
public String[] Authors { get; set; }

public override String ToString()
{
return Title;
}
}

static void Main()
{
List<Book> books = new List<Book>() {
new Book { Title="LINQ in Action" },
new Book { Title="JavaScript in Action" },
new Book { Title="CLR Via C#" } 
};

var titles =
books
.Where(book => book.Title.Contains("LINQ"))
.Select(book => book.Title);

ObjectDumper.Write(titles);
}
}

输出如下:

LINQ in Action

注意:查询语句与强类型数组的示例一模一样,没有作任何的改变,因为无论是数组还是列表都实现了同样的IEnumerable<Book>接口


3. 泛型字典


泛型字典实现了IEnumerable<KeyValuePair<TKey, TValue>>接口,KeyValuePair结构包含了强类型的Key和Value属性,以下列出主要的泛型字典:

System.Collections.Generic.Dictionary<TKey, TValue>
System.Collections.Generic.SortedDictionary<TKey, TValue>
System.Collections.Generic.SortedList<TKey, TValue>

示例如下:

class GenericDictionaryTest
{
static void Main()
{
Dictionary<int, string> numbers;
numbers = new Dictionary<int, string>();
numbers.Add(0, "America");
numbers.Add(1, "China");
numbers.Add(2, "England");
numbers.Add(3, "Australia");
numbers.Add(4, "French");
numbers.Add(5, "Japan");

//取键值为偶数的字典元素
var evenNumbers =
from number in numbers
where (number.Key & 1) == 0
select number.Value;

ObjectDumper.Write(evenNumbers);
}
}


4. 字符串

System.String看上去并不像是个集合,但它的确实现了IEnumerable<Char>接口,因此可以使用LINQ to Objects对其进行操作,示例如下:

class StringTest
{
static void Main()
{
var count =
"Do you know that man? I can't remember him!"
.Where(c => !Char.IsLetter(c))
.Count();
Console.WriteLine(count);
}
}

输出:11

注意:智能感知不会自动为String给出LINQ相关的扩展方法,因为很少有人将String作为IEnumerable<Char>处理


5. 其他集合

可以用LINQ to Objects与其他任何实现了IEnumerable<T>接口的集合配合使用,非泛型的集合实现了IEnumerable接口,却没有实 现IEnumerable<T>接口,不过可以借助Cast和OfType查询操作符对非泛型集合进行查询。


Linq之查询非泛型集合
Linq to object 中我们经常可以很方便的查询多种集合比如List<T>泛型,主要的原因是他们都实现了System.Collections.Generic.IEnumerable<T>接口从而可以完成相关的查询操作但并非所有的类都实现了以上接口比如说System.Collections.ArrayList,那么通过以下三种方式可以解决。

一、OfType操作符
先看它的签名 public  static IEnumerable<TResult> OfType<TResult>( this IEnumerable source)根据指定类型筛选IEnumerable的元素,当source为null返回ArgumentNullException

var q  =  cars.OfType < Car > ().Where(c => c.Doors == 2 );


二、Cast强制转换
从Cast的签名就知道它可以返回IEnumerable<T> ,
public static IEnumerable<T> Cast<T>(this IEnumerable source)
但是也要注意,如果被转换的类型中不能被转为T的则会报Invalid-
CastException异常,如果是null的话则为NullReferenceException上面代码改写为:
如果在它集合里面Cast有不转换的它就会抛出一个异常,只不过这里我们可以使用OfType(TResult)方法来过滤不被传换的,而不用抛出一个异常!
Console.WriteLine("OfType<T>() method");
            ArrayList fruits2 = new ArrayList(4);
            fruits2.Add("Mango");
            fruits2.Add("Orang2");
            fruits2.Add("Apple2");
            fruits2.Add(3.0);
            fruits2.Add("Banana2");

            IEnumerable<string> query4 = fruits2.OfType<string>();

            Console.WriteLine("Elements of type 'string' are:");

            foreach (string fruit in query4)
            {
                Console.WriteLine(fruit);
            }
var q  =  from c  in  cars.Cast<Car>
        
where  c.Doors == 2
        select 
new   {c.Name}


三、明确的类型定义
定义from中的查询类型,如

var q = from Car c in cars
        
where c.Doors==2
        select 
new {c.Name}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值