關於C#本質論和CLR via C#中譯本,不吐不快

来源:http://www.cnblogs.com/cairunbin/archive/2016/06/23/5606029.html
-Advertisement-
Play Games

C#本質論和CLR via C#兩本好書,周老師可能是俗務纏身,太忙了吧,翻譯得只能讓人呵呵了。 你要是忙,別接那麼多活好不啦。 現在都在說供給側改革,都在大力提倡工匠精神,我們做技術的,還是踏實點好,對不啦? 對照一下李建忠老師翻譯的那一版CLR via C#,差距啊。 這裡,僅把隨手發現的幾個問 ...


C#本質論和CLR via C#兩本好書,周老師可能是俗務纏身,太忙了吧,翻譯得只能讓人呵呵了。

你要是忙,別接那麼多活好不啦。

現在都在說供給側改革,都在大力提倡工匠精神,我們做技術的,還是踏實點好,對不啦?

對照一下李建忠老師翻譯的那一版CLR via C#,差距啊。

 

這裡,僅把隨手發現的幾個問題記錄一下,作為例子。

其實,在這兩本中譯本中,類似下麵的翻譯失當的例子隨處可見。如果你不深究,也就無所謂了,但如果你是認認真真地在學習這兩本書,這種無處不在的瑕疵,極度影響閱讀感受,甚至影響對原作者思想的理解。

周老師這兩本譯作出版之前可能沒有通讀一遍進行校核,否則,這些不合邏輯的話怎麼會沒有發現並修正呢?

當我們學習李建忠老師翻譯的那一版,就好像是同時在和兩大高手學習技藝。讀者不止從原作者那裡學習到了知識,還從譯者身上汲取很多營養,還能感受到譯者的嚴謹求實。

而拜讀周老師的譯作,咋說呢?反正只讀中譯本是看不懂,需要隨時參照原版去解讀中譯本。一本好書,從頭到尾一口氣讀完的酣暢淋漓的感覺完全找不到。對譯者失去了信任,讀起來總是要加著小心,很不爽。

 

當然, 必須說,從周老師的譯作中,我學習到了很多很多的知識。這裡,只是希望周老師能把工作做得更好,貢獻出更好的精品,以給我們這些C#的學習者更大的幫助。

 

C#本質論第四版

7.3.3 顯式介面實現與隱式介面實現的比較

原文:

The key difference between implicit and explicit member interface implementation
lies not in the syntax of the method declaration, but rather in
the ability to access the method by name through an instance of the type
rather than via the interface.

原書中的譯文:

對於隱式和顯式實現的介面成員,關鍵區別不在於成員聲明的語法,而在於通過類型的實例而不是介面訪問成員的能力。

應該的意思是:

採用顯式方式或者隱式方式來實現介面成員,其關鍵區別,並不在於聲明介面成員所採用的語法的不同,而是:隱式方式實現的介面成員可由類的實例對象直接調用,而顯式方式實現的介面,則必須首先將類的實例對象轉換為介面類型後方可調用。

7.5 節,224頁

原文:

In contrast, implementing ISettingsProvider assumes that there is
never a reason to have a class that can write settings without reading them.
The inheritance relationship between ISettingsProvider and IReadableSettingsProvider, therefore, forces the combined total of both interfaces on the ISettingsProvider class.

原書中的譯文:

相反,實現ISettingsProvider是基於這樣一個前提:任何類都不可能只能寫入而不能讀取設置。因此, ISettingsProvider、和IReadableSettingsProvider之間的繼承關係強迫在FileSettingsProvider類上合併這兩個介面。

合併兩個介面,呵呵,請問周老師,如何合併呢?

應該是:ISettingsProvider的設計者之所以採用繼承於IReadableSettingProvider,而不是將兩個介面相互獨立,併列提供給使用者,是基於這樣一個考慮:任何類都不可能只能寫入而不能
讀取設置。採用繼承的方式,則迫使使用者必須同時實現這兩個介面(一個寫入設置,一個讀出設置)。而如果採用兩介面相互獨立地併列提供給用戶的方式,則可能會導致用戶只實現寫入介面,而不實現讀取介面。這是不符合常規的。

 

227頁,關於利用介面實現多繼承

原文:

One possible improvement that works if the implemented members are methods (not properties) is to define interface extension methods for the additional functionality “derived” from the second base class. An extension method on IPerson could provide a method called VerifyCredentials(), for example, and all classes that implement IPerson—even an IPerson interface that had no members but just extension methods—would have a default implementation of VerifyCredentials(). What makes this approach viable is the fact that polymorphism is still available, as is overriding. Overriding is supported because any instance implementation of a method will take priority over an extension method with the equivalent static signature.

原書譯文:

如果被實現的成員是方法( 而非屬性) ,那麼有一個辦法可對此進行改進。具體就是 為從第二個基類"派生"的附加功能定義介面擴展方法。例如, 可為IPe內on定義擴展方法 Veri句Credentials() 。這樣,實現IPerson ( 即使IPerson介面沒有成員,只有擴展方法) 的 所有類都會再lerifyC陀dentials()的預設實現。這之所以可行,完全是多態性和重寫的功勞。之所以支持重寫, 是因為方法的任何實例實現都要優先於具有相同靜態簽名的擴展方法。

我不是很清楚原書中論述的關於多態的思想和技術,但是,我感覺後面加黑體的這句話應該這麼翻譯才對:

這之所以可行,是因為這樣的事實:當overriding時,多態機制依然有效。因為方法的實例實現(就是在類中定義的實現)的優先順序是高於具有相同靜態簽名的擴展方法的實現的。

感覺原文作者是這個意思吧:當你以實例方法的形式重寫與介面方法靜態簽名相同的擴展方法後,由於實例方法優先順序高,所以在使用過程中,實例方法會被優先調用,這也就實現了多態。因此,採用介面擴展方法實現多繼承的方案是可行的。因為,當採用多基類繼承方式的時候,是完美支持多態的,如果以介面擴展方法的方式實現多繼承功能時不能完美支持多態,則該方式是不可行的。

 

309頁 小標題 11.2.2 簡單泛型類的定義

 原文標題:Defining a Simple Generic Class

原作者的意思應該是“定義一個簡單的泛型類”。這一小節實際上是以一個非常簡單的泛型類為例,讓讀者對泛型類的定義有一個簡單的瞭解而已。翻譯成簡單泛型類的定義,反正我的第一感覺是有那麼一個泛型類,叫做簡單泛型類,然後,我要去找複雜泛型類了。

 

311頁 關於泛型參數

原文:

Note that it is legal, and indeed common, for the type argument for one generic type to be a type parameter of another

原書譯文:

註意,一個泛型的類型實參可以成為另一個泛型類型的類型參數。

這句翻譯只能是譯者本人清楚這句話想表達的意思,讀者是看不懂的。

原文是說,一個泛型類的類型參數可以作為另一個泛型類的類型參數。 

翻譯文本中,前後定語不一致,前面是泛型的,後面是泛型類型的,這看起來就像是故意把讀者繞進去。

 

 320頁 關於泛型的介面約束

原文:

When calling a method on a value typed as a generic type parameter, the compiler checks whether the method matches any method on any of the interfaces declared as constraints.

原書譯文:

如果傳遞的類型實參是值類型,那麼在調用它的方法時,編譯器會檢查方法是否與在約束中指定的任何介面的任何方法相匹配。

這翻譯我也是醉了,能嚴謹一點不?翻譯出來的東西,起碼自己讀得懂吧?

值類型 ,應該是Value type,這裡作者是value typed,斷句啊。原文省略了兩個單詞而已,應該是:When calling a method on a value which is typed as a generic type parameter, the compiler checks whether the method matches any method on any of the interfaces declared as constraints. 這裡的value,應該是variable的意思,就是一個變數,一個值。

原文應該的意思是:當作為泛型類型傳遞進來的變數調用某一方法時,編譯器會檢查這個方法與介面約束中指定的那些介面所定義的各個方法是否有匹配。這句的翻譯還要參考上下文的。原書上文中說,在泛型方法中調用介面的方法,不需要將泛型變數轉換為介面類型,即使被調用的方法是顯式實現的。(這在其他語境中是不可以的)。所以,這句話只是對“不需要將泛型變數轉換為介面類型”這件事做一個解釋而已,解釋一下為什麼不需要進行轉換。

 

331頁 關於協變與逆變

原文:

An IPair<PdaItem> can contain an address, but the object is really a Pair<Contact> that can contain only contacts, not addresses. Type safety is completely violated if unrestricted generic covariance is allowed.

與上述原文相關的一段源代碼:

Contact contact1 = new Contact("Princess Buttercup"),
Contact contact2 = new Contact("Inigo Montoya");
Pair<Contact> contacts = new Pair<Contact>(contact1, contact2);
// This gives an error: Cannot convert type ...
// But suppose it did not.
// IPair<PdaItem> pdaPair = (IPair<PdaItem>) contacts;
// This is perfectly legal, but not type-safe.
// pdaPair.First = new Address("123 Sesame Street");

 

原書譯文:

IPair<Pdaltem> 中可以包含地址,但Pair <Contact>對象只能包含聯繫人,不能包含地址。若允許不受限制的泛型協變性,類型安全將完全失去保障。

這翻譯的,估計譯者都不知道自己在說啥。

這句話,確實較難理解。特別是結合全書的上下文。這其實也有原作者的不嚴謹導致了出現問題。

在整本書中,一直採用PdaItem類、Contact類以及其它幾個類做例子來講解各種概念。(其實,個人感覺,這幾個類本身關係就很牽強,並不適合做例子講解各種基本概念)。

其中,Contact類中有一個欄位是address(地址),而PdaItem類中,是沒有這個欄位的。

但是,綜合上下文,這句中的address(原書錯誤,應該大寫首字母,是Address),其實是指名為Address的一個類,且這個類繼承於PdaItem。但是,原書中並未交代,樣例代碼也未說明。這就導致譯者和其它原文讀者的困惑。

明白了這一點,原文就容易理解了。

原文的意思應該是:IPair<PdaItem>中,可以容納Address對象(因為Address從PdaItem派生),但是,IPair<PdaItem> pdaPair本身是Pair<Contact>對象,只能容納Contact對象,而無法容納Address對象。這就直接破壞了類型安全。

原書有錯誤,並不是你也跟著犯錯的合理理由。否則豈不以訛傳訛了。

其實道理很簡單,就是List<String>類型的變數,不能賦值給List<Object>類型的變數listObj。因為,listObj實際上是List<String>類型,但從字面上看,其卻是List<Object>類型。若哪一個用戶將一個int變數放進來,豈不是會發生問題?這就導致類型不安全的問題發生。

 

 還是331頁 關於協變與逆變

原文:

Now it should also be clear why a list of strings may not be used as a list of objects. You cannot insert an integer into a list of strings, but you can insert an integer into a list of objects; thus it must be illegal to cast a list of strings to a list of objects, an error the compiler can enforce.

原書譯文:

 現在應該很清楚為什麼字元串列表不能作為對象列表使用了。在字元串列表中不能插入整數,但在對象列表中可以插入整數, 所以從字元串列表轉型成對象列表一定要被視為非法,使編譯器能預防錯誤。

 這翻譯實在是不走心。

實際上,該段的上文中舉了個例子,說List<string>不能賦值給List<object>。所以,這裡的list of objects,實際上是List<object>,周老師你怎麼能直接翻譯成對象列表了?啥是對象列表?真是無語了。麻煩你在下一版中把對象列表替換為List<object>、捎帶著把字元串列表替換為List<string>。

 

 

歡迎大家把發現的問題跟帖回覆。也可以把原書中敘述不清楚的地方貼出來大家一起討論。我也會把後續發現的問題繼續在這裡更新。

希望下一版的這兩本書能更完善,給讀者一個更好的感受。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • #卸載mysql /etc/init.d/mysqld stop &> /dev/null killall mysqld &> /dev/null sudo rm -rf /mengdi/server/mysql &> /dev/null sudo rm -rf /mengdi/server/mys ...
  • nmon 下載:http://pan.baidu.com/s/1jICoSpo 放到linux下可以直接運行。 nmon 工具可以幫助在一個屏幕上顯示所有重要的性能優化信息,並動態地對其進行更新。 nmon 工具可以為 AIX 和 Linux 性能專家提供監視和分析性能數據的功能,其中包括: CPU ...
  • 三個文件夾,第一個是放置前端部分,第二個是各種支持的類文件,第三個是單元測試文件。 Core文件類庫 放置的是與資料庫做交互的文件,以及一些第三方類庫,還有與資料庫連接的文件 1.Lasy.Validator是一個基於Attribute驗證器,我覺得這種驗證方式在挺便捷的,具體可以在這裡查看到htt ...
  • 這些對象都是用來保存信息的,包括用戶信息,傳遞值的信息,全局信息等等。下麵主要說一下他們之間的區別: 1.Application對象 Application用於保存所有用戶的公共的數據信息,如果使用Application對象,一個需要考慮的問題是任何寫操作都要在Application_OnStart ...
  • 引言 HTTP 是一個屬於應用層的面向對象的協議,由於其簡捷、快速的方式,適用於分散式超媒體信息系統。它於1990年提出,經過幾年的使用與發展,得到不斷地完善和 擴展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的規範化工作正在進行之中,而且HTTP-NG(Next Genera ...
  • 背水一戰 Windows 10 之 綁定: 與 Element 綁定, 與 Indexer 綁定, TargetNullValue - 當綁定數據為 null 時顯示的值, FallbackValue - 當綁定失敗時顯示的值 ...
  • EF和SqlHelper 簡單三層 EF生成sql,再調用ado.net訪問資料庫,最後使結果對象具體化. 之前的SqlHelper 簡單三層的寫法,拼接sql語句字元串,再調用ado.net訪問資料庫,最後也是把結果轉換為對象. 明顯的區別:sql語句的產生,EF是SQL查詢命令和 LINQ 查詢 ...
  • 前言 老規矩,任何技術的入門我通常都會總結增刪改查,本文我就通過HttpWebRequest和SolrNet的方式實現Solr最基礎的增刪改查(CURD)。對於自己的完整項目,同時不想過於依賴第三方類庫的則通過Http介面的方式來調用Solr。 當然也有人喜歡調用第三方的類庫,簡單方便,不需要自己處 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...