湖边的白杨树

探索是一种乐趣

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

 

C# LINQ 基础
1. LINQ 查询语句
   所有 LINQ 查询操作都由以下三个不同的操作组成:
  1) 获取数据源。
  数据源需要支持“可查询类型”。(支持 IEnumerable<T> 或派生接口(如泛型 IQueryable<T>)的类型称为“可查询类型”。)
  a. 数组
  b. LINQ to XML.
  c. LINQ to SQL.
  d. 支持非泛型 IEnumerable 接口的类型(如 ArrayList)也可用作 LINQ 数据源

  2) 创建查询。
  查询表达式
  from 字句指定数据源
  where 字句应用筛检器
  select 字句指定返回的元素的类型
  在 LINQ 中,查询变量本身不执行任何操作并且不返回任何数据。它只是存储在以后某个时刻执行查询时为生成结果而必需的信息。

  3) 执行查询。
  a.延迟执行
  查询变量本身只是存储查询命令。实际的查询执行会延迟到在 foreach 语句中循环访问查询变量时发生。此概念称为“延迟执行”
  在 foreach 语句中执行查询,而 foreach 要求使用 IEnumerable 或 IEnumerable<T>。

  b.强制立即执行
  对一系列源元素执行聚合函数的查询必须首先循环访问这些元素。Count、Max、Average 和 First 就属于此类查询。由于查询本身必须使用 foreach 以便返回结果,因此这些查询在执行时不使用显式 foreach 语句。另外还要注意,这些类型的查询返回单个值,而不是 IEnumerable 集合。

下面的查询返回源数组中偶数的计数:

int evenNumCount = evenNumQuery.Count(); 


若要强制立即执行任意查询并缓存其结果,可以调用 ToList<TSource> 或 ToArray<TSource> 方法

List<int> numQuery2 =
(from num in numbers
where (num % 2) == 0
select num).ToList();


// or like this:
// numQuery3 is still an int[]


var numQuery3 =
(from num in numbers
where (num % 2) == 0
select num).ToArray();
static void Main(string[] args)
{
// 1. 设定数据源
int[] numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7 };


// 2. 设置查询条件. 这里的query的类型是 IEnumerable<int>
var query = from num in numbers
where (num % 2) == 0
select num;


// 3. 执行查询, 获取结果.
Console.WriteLine(" Even numbers are: ");
foreach (int num in query)
{
Console.Write(" {0} ", num);
}


Console.ReadLine(); 
}

 

2. LINQ 方法查询。

在表示语言集成查询 (LINQ) 使用 LINQ 性查询语法,文档中的多数查询编写。 但是,在中,当编译代码时,必须将查询语法转换方法需要 .NET 公共语言运行时 (CLR)。 这些方法调用标准查询运算符,的名称类似WhereSelectGroupByJoinMax和 Average 可以调用这些方法直接使用方法语法而不是查询语法

int[] numbers = { 5, 10, 8, 3, 6, 12};

        //Query syntax:
        IEnumerable<int> numQuery1 = 
            from num in numbers
            where num % 2 == 0
            orderby num
            select num;

        //Method syntax: 等效于上面的LINQ查询语句。
        IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);

 

3. List 与 Linq

很多时候,从一个关系表中挑出一个我们需要的元素列表采用SQL语句是再容易不过的了,其实C#的List中也可以采用类似的方法,虽然List中集成了Select(), Where()等语句,不过如果你的判断规则较为复杂,或者想要看起来一目了然,以下的方法也是可行的:

首先假设你有一个类

public class People
{
    public string Name { get; set; }
    public int Age { get; set; }
}
并且有一些初始化语句
List<People> PeopleList = new List<People>();
PeopleList.Add(new People() { Name = "Haocheng Wu", Age = 24 });
PeopleList.Add(new People() { Name = "Haocheng Wu", Age = 25 });
PeopleList.Add(new People() { Name = "James Wu", Age = 23 });

你就可以采用下面类似于SQL语句的方法进行select

List<string> SubPeopleNameList1 = (from people in PeopleList
                              where people.Name == "Haocheng Wu" && people.Age == 24
                              select people.Name).ToList<string>();

当然你也可以用一行代替
 
List<string> SubPeopleNameList2 = PeopleList.Where(people => people.Name == "Haocheng Wu" && people.Age == 24).Select(people => people.Name).ToList();

不过显然第一种方法更加一目了然,尤其是当判断条件相当复杂的时候就更加有用了

 

4. Array 与 Linq

查询一组数组中其中几个数值的平均值。

            double[] brights = new double[] { 0, 1, 2, 999, 4, 5, 6, 7, 8, 9, 10 };

            double avg = brights.Where(value => value != 999).Average(); 

剔除指定位置后,取最小,最大值。

            double[] maxBrightnesses = new double[]
            {
                1, 2, 3, 4, 11, 6, 7, 8, 9, 10, 
            };

            int indexOfCapsLockLed = 4; 

            double minValueOfKeyPixelMax = maxBrightnesses.Where((value, index) => index != indexOfCapsLockLed).Min();
            double maxValueOfKeyPixelMax = maxBrightnesses.Where((value, index) => index != indexOfCapsLockLed).Max();

 查询两个数组的交集。

            string[] a = new string[] { "A", "B", "C", "C", "B", "D" };

            string[] b = new string[] { "a", "B", "c", "C", "b", "d" };

            string[] c = new string[] { "a", "b", "c", "c", "b", "d" };

            string[] commonAB = a.Intersect(b).ToArray();

            string[] commonAC = a.Intersect(c).ToArray();

            // The length of commonAC array is 0. 
            Console.WriteLine("{0}", commonAC.Length);

 int[] arr = new int[3];
int[] arr2 = new int[3];
// 省略为 arr、arr2 赋值

int[] arr3 = arr.Intersect(arr2).ToArray(); // 交集
int[] arr4 = arr.Except(arr2).ToArray(); // 差集
int[] arr5 = arr.Union(arr2).ToArray(); // 并集(arr5 = arr1 + arr2)

参考:http://msdn.microsoft.com/zh-cn/library/bb397906(v=vs.90).aspx

 

Distinct()

用 List 的 Distinct()方法来筛选List中的唯一值。不能直接简单的使用Distinct(),其函数是基于默认的GetHashCode()方法的,由于class是引用变量,所以不能直接进行对值的比较。

实现的方法有两种

1. Overwrite list中的class 的 Equial 和 GetHashCode 方法。

2. 自定义Compairer.

Reports = this.GetReports().Distinct(new InfoComparer()).ToArray();
IEqualityComparer<MyClass>
    {

        public bool Equals(MyClass objA, MyClass objB)
        {
            if (object.ReferenceEquals(objA, objB))
            {
                return true;
            }

            if (object.ReferenceEquals(objA, null) || object.ReferenceEquals(objB, null))
            {
                return false;
            }

            return objA.member1 == objectB.member2 
&&objectA.member2==objectB.member2;
        }


        public int GetHashCode(MyClass obj)
        {
            if (object.ReferenceEquals(obj, null))
            {
                return 0;
            }

            return obj.member1.GetHashCode()^obj.member2.GetHashCode();
        }

 

 

 

 

posted on 2013-04-15 17:27  fdyang  阅读(363)  评论(0编辑  收藏  举报