码迷,mamicode.com
首页 > 其他好文 > 详细

什么是LINQ? (上)

时间:2014-11-23 00:31:07      阅读:348      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   ar   color   os   使用   sp   

  什么是LINQ?LINQ(Language Integrated Query)的全称就是语言集成查询,是为了各种不同的数据源提供一个统一的接口。通过这个接口,查询各种数据源可以使用将近一致的方式和语法。根据各种不同的数据源,接口有着不同的实现。而接口的调用者,通常是各种各样的应用程序。根据数据源的不同,产生了不同的LINQ分支,如LINQ To Objects, LINQ To SQL, LINQ To XML等。下面先简单说一下LINQ涉及到的基础知识。

  一、泛型委托

   委托是方法的抽象,泛型是类型的抽象,他们两个的组合使得我们可以定义任意参数和返回值的方法。我们只要批量定义一组委托,这些委托的参数个数是不同的,返回值和参数类型全部都是泛型的,那就可以表示某一参数个数范围内的任意方法了。.Net有两种委托,一种是Func<T,TResult>,T代表参数类型,TResult是返回值类型,另一种是Action<T>,Action和Func类似,但是不包含返回值。

  二、隐式类型和匿名类型

  在声明一个隐式类型时,必须对它赋值。而且var只能用于局部变量,不能将字段、属性和方法的返回值声明为隐式类型。值得注意的是,使用var声明一个隐式类型,该变量依然能够使用该类型的方法,也就是说编译器能智能识别该局部变量。

var _linq = "LINQ";

  隐式类型最好跟匿名类型结合使用。单独使用隐式类型的声明会使得代码可读性变差。匿名类型允许我们直接创建类型的实例,而不必预先定义该类型。也就是说,没有这个类,凭空生成一个对象。

var s = new {name = "Jack"};

  三、扩展方法

  什么是扩展方法?扩展方法通过编写一个新的类给原来的类增加新的方法。有两个要求:扩展方法所在的类必须为静态类且扩展方法必须是静态方法;被扩展的类型作为扩展方法的第一个参数传递进去,并且前面加上this关键字。通常扩展方法所在的类型使用Extension作为结尾。注意别把扩展方法声明为内部类。

  

public static class StringExtension{
    public static void SayHello(this string str){Debug.Log ("hello!");}
}

  现在可以使用这个扩展方法了。

string jack = "jack";
jack.SayHello ();

  四、匿名方法和Lambda表达式

  就像隐式类型声明和匿名对象有较好的契合一样,匿名方法和Lambda表达式也有很深的关系。匿名方法有什么用?匿名方法允许我们将代码块传递为委托参数,并且减少了实例化委托所需的编码系统开销。例如下面的例子,我们不必实际写一个方法,再让委托等于该方法了。

public delegate void myDelegate();
myDelegate md;
md = delegate() {Debug.Log ("匿名方法");};

  匿名方法使用delegate关键字声明,后面跟着方法的参数列表,然后在花括号中编写方法的内容。假如不需要用到方法的参数时,可以将参数列表省略。考虑到这一点,我们可以将匿名方法转换为具有各种参数的委托。但是这个好像没有多大意义,因为你都把参数列表忽视了呀。

public delegate void anotherDelegate(string name);
anotherDelegate ad;
ad = delegate {Debug.Log("一个参数的匿名方法");};  

  此外,我们还可以直接在方法里面访问在方法外部声明的变量。

  什么是Lambda表达式?Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数。Lambda表达式省略了delegate关键字,也省略了参数类型。Lambda运算符=>左边是参数,右边是方法体。假如方法体不止一行,就要加上花括号。如果没有花括号呢,默认就把方法体的执行结果作为返回值,假如有了花括号,必须使用return关键字来明确返回执行结果。

ad += (x)=>Debug.Log(x);

  详细的关于Lambda表达式:http://msdn.microsoft.com/zh-cn/library/bb397687.aspx

   五、集合

  什么是集合?集合有以下特性:

  1、可以通过索引或键来访问集合的成员,如collection[index]或collection[key]。

  2、可以使用for、foreach进行遍历

  3、提供一些方法,用于获得集合成员数量、添加和移除成员,如Count,Length,Add(),Remove(),Clear()等。

  现在我们自己创建一个Product类。

using UnityEngine;
using System.Collections;

public class Product {
    public int id { get; set;}
    public string code { get; set;}
    public string _name { get; set;}

    public static ProductCollection GetSampleCollection(){
        ProductCollection collection = new ProductCollection (
            new Product[]{new Product(){id =1, code = "1001", _name = "wine"},
            new Product(){id =2, code = "1002", _name = "wine"},
            new Product(){id =3, code = "1003", _name = "wine"},
            new Product(){id =4, code = "1004", _name = "wine"},
            new Product(){id =5, code = "1005", _name = "wine"},
            new Product(){id =6, code = "1006", _name = "wine"},
            new Product(){id =7, code = "1007", _name = "wine"},
            new Product(){id =8, code = "1008", _name = "wine"}}
            );
        return collection;
    }

    public override string ToString ()
    {
        return string.Format ("[Product: id={0}, code={1}, _name={2}]", id.ToString(), code, _name);
    }
}

  接下来创建一个集合类ProductCollection。

using UnityEngine;
using System.Collections;
using System;

public class ProductCollection{
    private Hashtable hashtable;
    public ICollection Keys{ get{ return hashtable.Keys;}}
    public ProductCollection(params Product[] items){
        hashtable = new Hashtable ();
        foreach (Product item in items) {
            this.Add(item);
        }
    }
    public void Add(Product item){
        hashtable.Add (item.code, item);
    }
    public int Count {get { return hashtable.Keys.Count;}}
    public string GetKey(int index){
        if(index<0 || index>hashtable.Keys.Count)
            throw new Exception("index is out of range");
        string selected = "";
        int i = 0;
        foreach (string item in hashtable.Keys) {
            if(i == index){
                selected = item;
                break;
            }
            i++;
        }
        return selected;
    }    

    public Product this[int index]{
        get{
            string key = GetKey(index);
            return hashtable[key] as Product;
        }
    }
}

  下面测试一下这两个类。

using UnityEngine;
using System.Collections;

public class _Test : MonoBehaviour {

    // Use this for initialization
    void Start () {
        ProductCollection collection = Product.GetSampleCollection ();
        Debug.Log (collection.Count);
        Debug.Log (string.Format("第{0}个下标的键是{1}","6",collection.GetKey(6)));
        for (int i = 0; i < collection.Count; i++) {
            string line = collection[i].ToString();
            Debug.Log(line);
                }
    }
}

  可以看到ProductCollection类已经可以使用[]操作符来访问对象。如果想让ProductCollection类支持foreach循环,需要实现IEnumerable<T>接口。

public interface IEnumberable<out T> :IEnumerable{
    IEnumerator<T> GetEnumerator();
}

  IEnumerable<T>接口实现了IEnumerable接口。

public interface IEnumerable{
    IEnumerator GetEnumerator();
}

  我们通过编写一个类来实现这两个接口。这个类应该实现IEnumerator<T>接口。而IEnumerator<T>接口又实现了IEnumerator和IDisposable接口。

public interface IEnumerator<out T> :IDisposable, IEnumerator{
  T Current { get;}  
}
public interface IEnumerator{
  object Current {get;}
  bool MoveNext();
  void Reset();      
}
public interface IDisposable{
  void Dispose();  
}

  下面往刚才的类里添加几行代码。这只是类的前面部分,重复的省略了。

public class ProductCollection : IEnumerable<Product>{

    public class ProductEnumerator :IEnumerator<Product>{
        private ProductCollection collection;
        private int index;
        public ProductEnumerator (ProductCollection col){
            this.collection = col;
            index = -1;
        }

        public Product Current{get { return collection[index];}}

        object IEnumerator.Current{get { return collection[index];}}

        public bool MoveNext(){
            index ++;
            if (index >= collection.Count)
                                return false;
                        else
                                return true;
        }

        public void Reset(){ index = -1;}

        public void Dispose(){}
    }

    public IEnumerator<Product> GetEnumerator(){
        return new ProductEnumerator (this);
    }

    IEnumerator IEnumerable.GetEnumerator(){
        return new ProductEnumerator (this);
    }
  //省略重复代码
}

  现在可以使用迭代器遍历我们的ProductCollection了。

//第一种遍历方式
IEnumerator<Product> p = collection.GetEnumerator ();
    while (p.MoveNext()) {
        string line = p.Current.ToString();
        Debug.Log(line);
}

//第二种遍历方式
foreach (Product p in collection) {
    string line = p.ToString();
    Debug.Log(line);
}

   所有实现了IEnumerable<T>的对象,都可以进行遍历,描述这类对象的术语叫做序列。序列仅仅关心是否可以遍历。

什么是LINQ? (上)

标签:style   blog   http   io   ar   color   os   使用   sp   

原文地址:http://www.cnblogs.com/amazonove/p/4115397.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!