• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Javen-Studio 咖啡小屋

            http://javenstudio.org - C++ Java 分布式 搜索引擎
            Naven's Research Laboratory - Thinking of Life, Imagination of Future

              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              24 隨筆 :: 57 文章 :: 170 評論 :: 4 Trackbacks

            3.2         擴展方法(Extension Methods

            Lambda表達式是查詢體系(query architecture)的一個重要部分,擴展方法(Extension methods)是另一個重要組成部分。擴展方法結(jié)合了“duck typing”(一種可替代任何類型的類型)的彈性(flexibility)特點,使得動態(tài)語言(dynamic languages,如JavaScript)更加流行(popular),同時又有靜態(tài)型語言(statically typed languages,如C++Java)的優(yōu)秀性能(performance)和編譯時驗證(compile-time validation)的特點。通過擴展方法,第三方(third parties)可以增加使用了新方法的類型(type with new methods)的公共合同(public contract),使得獨立型的開發(fā)者(individual type authors)還能提供他們對這些方法的自己專門的實現(xiàn)(specialized implementation)。

             

            擴展方法定義在靜態(tài)類(static classes)里,就像靜態(tài)方法(static methods)一樣,但是它們在CLR元數(shù)據(jù)(CLR metadata)里卻被標記為[System.Runtime.CompilerServices.Extension]。程序語言都被鼓勵(encourage)為擴展方法提供一種直觀的語法(direct syntax)。在 C# 語言里,擴展方法是由 this 指針(this modifer)標示(indicate)的,它必須應(yīng)用于(applied to)擴展方法的第一個參數(shù)。下面讓我們來看看一段最簡單的查詢操作符(query operator)的定義代碼:

             

            namespace System.Query {
              
            using System;
              
            using System.Collections.Generic;

              
            public static class Sequence {
                
            public static IEnumerable<T> Where<T>(
                         
            this IEnumerable<T> source,
                              Func
            <T, bool> predicate) {

                  
            foreach (T item in source)
                    
            if (predicate(item))
                      yield 
            return item;
                }

              }

            }

             

            擴展方法的第一個參數(shù)的類型標示(indicate)擴展的內(nèi)容所應(yīng)用(the extension applies to)的類型。在上面的例子中,擴展方法 Where 擴展自 IEnumerable<T> 類型。因為 Where 是一個靜態(tài)方法(static method),所以我們可以像其他靜態(tài)方法一樣直接調(diào)用它(invoke it directly):

             

            IEnumerable<string> expr = Sequence.Where(names, 
                                                      s 
            => s.Length < 6);

             

            然而,擴展方法的一個獨特(unique)的特點是我們還可以使用實例的語法(using instance syntax)來調(diào)用它:

             

            IEnumerable<string> expr = names.Where(s => s.Length < 6);

             

            擴展方法是基于擴展方法的活動范圍內(nèi)(in scope)在編譯時(compile-time)決定的(resolved)。當引入(import)一個命名空間(namespace)時(在 C# 里使用 using 語句,在VB 里使用 Import 語句),所有的擴展方法是由從 namespace 帶入活動范圍(brought into scope)的靜態(tài)類(static classes)定義的。

             

            標準查詢操作符(standard query operators)在 System.Query.Sequence 類型里定義成擴展方法。當檢查標準查詢操作符時,你將注意到它們中所有的方法根據(jù)(in terms of)接口IEnumerable<T> 來定義的(除了 OfType,將在后面介紹它)。這意味著每一個兼容 IEnumerable<T> 接口的信息源(information source)在 C# 語言里通過簡單地添加如下的 using 語句就可以獲取標準查詢操作符:

             

            using System.Query; // makes query operators visible

             

            用戶如果想用一個指定的類型(specific type)來替換標準查詢操作符,可以在有一致標識(compatible signatures)的指定的類型上定義他們自己的相同名字的方法(same-named methods),另一種方法是通過擴展指定的類型來(extend the specific type)定義相同名字的方法。用戶如果想完全避免(eschew)使用標準查詢操作符,可以簡單地將 System.Query 置于活動范圍之外,并且為 IEnumerable<T> 接口寫出他們自己的擴展方法就可以了。

             

            按照分析規(guī)則,擴展方法被賦予了最低優(yōu)先權(quán)(lowest priority),它們只是在沒有相適配(suitable)的目標類型(target type)和它們的基類型(base types)時才被使用。這個規(guī)則允許用戶自定的類型(user-defined types)提供他們自己的查詢操作符,比標準查詢操作符更優(yōu)先使用(take precedence over)。例如,考慮用戶自定義 collection 的實現(xiàn)如下:

             

            public class MySequence : IEnumerable<int> {
              
            public IEnumerator<int> GetEnumerator() {
                
            for (int i = 1; i <= 10; i++
                  yield 
            return i; 
              }


              IEnumerator IEnumerable.GetEnumerator() 
            {
                
            return GetEnumerator(); 
              }


              
            public IEnumerable<int> Where(Func<intbool> filter) {
                
            for (int i = 1; i <= 10; i++
                  
            if (filter(i)) 
                    yield 
            return i;
              }

            }

             

            通過給出這個類的定義,下面的程序:

             

            MySequence s = new MySequence();
            foreach (int item in s.Where(n => n > 3))
                Console.WriteLine(item);

             

            將使用 MySequence.Where 的實現(xiàn),而不是擴展方法,因為類實體方法(instance methods)比擴展方法(extension methods)更優(yōu)先使用。

             

            前面的提及(mentioned earlier)了屬于標準操作符(standard operator)一員但不是擴展自基于IEnumerable<T> 接口(IEnumerable<T>-based)的信息源的 OfType 類型,下面讓我們來看看 OfTyoe 查詢操作符:

             

            public static IEnumerable<T> OfType<T>(this IEnumerable source) {
              
            foreach (object item in source) 
                
            if (item is T) 
                  yield 
            return (T)item;
            }

             

            OfType 即接受基于IEnumerable<T> 接口的信息源,也接受那些在 .NET Framework 1.0 中出現(xiàn)的非參數(shù)化的 IEnumerable 接口(non-parameterized IEnumerable interface)。OfType 操作符允許用戶在標準的 .NET collections (classic .NET collections)上應(yīng)用標準查詢操作符,就像下面的程序:

             

            // "classic" cannot be used directly with query operators
            IEnumerable classic = new OlderCollectionType();

            // "modern" can be used directly with query operators
            IEnumerable<object> modern = classic.OfType<object>();

             

            在這個例子中,變量 modern 產(chǎn)生了與變量 classic 一樣的順序的數(shù)據(jù)列表(same sequence of values),但是不同的是它的類型兼容最新的 IEnumerable<T> 代碼(modern IEnumerable<T> code),包括標準查詢操作符。

             

            OfType 操作符對新的信息源也是有用的,因為它允許從基于類型的信息源(source based on type)中過濾出數(shù)據(jù)(filtering values from)。當要制作新的順序的時候(producing the new sequence),OfType 簡單的忽略(omits)原有序列的成員(members of the original sequence)就可以了,這是與類型實參(type argument)不相符的。分析下面的程序,目標是將 string 字符串數(shù)據(jù)從一個有不同種類數(shù)據(jù)的數(shù)組(heterogeneous array)中分解出來:

             

            object[] vals = 1"Hello"true"World"9.1 };
            IEnumerable
            <string> justStrings = vals.OfType<string>();

             

            當在 foreach 語句中列舉(enumerate)變量 justStrings 中的數(shù)據(jù)時,將得到兩個依次為“Hello”和“World”的 string 字符串序列(a sequence of two strings )。

             

            待續(xù), 錯誤難免,請批評指正,譯者Naven 2005-10-22

            posted on 2005-10-22 22:30 Javen-Studio 閱讀(1345) 評論(3)  編輯 收藏 引用

            評論

            # re: 擴展方法(Extension Methods) 2008-01-16 17:38 蜜桃
            為什么留那么多沒有必要的原文,看的眼花繚亂?
            既然是翻譯,除了會引起歧義的,就沒有必要留那么多原文。  回復(fù)  更多評論
              

            # re: 擴展方法(Extension Methods) 2008-01-16 17:43 Javen-Studio
            哦,為了方便對照著看,感覺這樣會看得更仔細些:)  回復(fù)  更多評論
              

            # re: 擴展方法(Extension Methods) 2008-11-18 01:12 GUYUE
            看來 mitao 對自己的英文翻譯很有把握啊...
            不過,怎么不看見你也這么認真仔細的翻譯這么好的文章呢??



            謝謝分享.萬分感謝。  回復(fù)  更多評論
              


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            久久精品国产亚洲AV高清热| 久久亚洲日韩看片无码| 久久综合给合久久狠狠狠97色| 欧美久久精品一级c片片| 久久久久久久综合日本| 久久精品国产免费一区| 久久国产精品成人片免费| 久久99国内精品自在现线| 久久天堂电影网| 亚洲精品乱码久久久久久不卡| 欧美日韩精品久久免费| 成人久久综合网| 欧美性大战久久久久久| 天天爽天天狠久久久综合麻豆| 99精品久久精品| 色婷婷噜噜久久国产精品12p| 久久精品国产日本波多野结衣| 浪潮AV色综合久久天堂| 国产精品内射久久久久欢欢| 欧美日韩精品久久免费| 国产成人无码精品久久久免费 | 99久久夜色精品国产网站| 国产精品成人99久久久久91gav| 伊色综合久久之综合久久| 亚洲va久久久噜噜噜久久男同| 9191精品国产免费久久| 中文国产成人精品久久不卡| 国产精品九九久久精品女同亚洲欧美日韩综合区 | 久久精品国产只有精品66| 无码人妻久久一区二区三区| 久久久国产精华液| 久久综合九色综合97_久久久| 一本大道久久香蕉成人网| 日本免费一区二区久久人人澡| 亚洲成色www久久网站夜月| 亚洲国产综合久久天堂| 国产精品狼人久久久久影院| 精品久久久久久国产91| 久久久久成人精品无码中文字幕| 久久乐国产综合亚洲精品| 久久精品一区二区三区中文字幕|