適合 Java 開發人員的 XamarinXamarin for Java developers

如果您是 JAVA 開發人員,您可以充分利用 Xamarin 平臺上的技能和現有程式碼,同時享受的程式碼重複使用優勢C#。您會發現C#語法與 JAVA 語法非常類似,而且這兩種語言都提供非常類似的功能。此外,您還將探索特有C#的功能,讓您的開發工作更輕鬆。If you are a Java developer, you are well on your way to leveraging your skills and existing code on the Xamarin platform while reaping the code reuse benefits of C#. You will find that C# syntax is very similar to Java syntax, and that both languages provide very similar features. In addition, you'll discover features unique to C# that will make your development life easier.

概觀Overview

本文提供適用於 Java 開發人員的 C# 程式設計簡介,主要著重於您在開發 Xamarin.Android 應用程式時可能遇到的 C# 語言功能。This article provides an introduction to C# programming for Java developers, focusing primarily on the C# language features that you will encounter while developing Xamarin.Android applications. 此外,本文將說明這些功能與其 Java 對應項目之間的差異,並介紹無法在 Java 中使用的重要 C# 功能 (與 Xamarin.Android 相關)。Also, this article explains how these features differ from their Java counterparts, and it introduces important C# features (relevant to Xamarin.Android) that are not available in Java. 還會提供與其他參考資料的連結,讓您可以使用本文作為進一步研究 C# 和 .NET 的「出發點」。Links to additional reference material are included, so you can use this article as a "jumping off" point for further study of C# and .NET.

如果您熟悉 Java,將能立即感受到 C# 的語法。If you are familiar with Java, you will feel instantly at home with the syntax of C#. C# 語法與 Java 語法非常類似 – C# 是一種類似 Java、C 及 C++ 的「大括號」語言。C# syntax is very similar to Java syntax – C# is a "curly brace" language like Java, C, and C++. 在許多方面,C# 語法的讀取方式就像 Java 語法的超集,但有一些重新命名和新增的關鍵字。In many ways, C# syntax reads like a superset of Java syntax, but with a few renamed and added keywords.

您可以在 C# 中找到多個 Java 的主要特性:Many key characteristics of Java can be found in C#:

  • 以類別為基礎的物件導向程式設計Class-based object-oriented programming

  • 強類型Strong typing

  • 支援介面Support for interfaces

  • 泛型Generics

  • 記憶體回收Garbage collection

  • 執行階段編譯Runtime compilation

Java 和 C# 都會編譯為要在受控執行環境中執行的中繼語言。Both Java and C# are compiled to an intermediate language that is run in a managed execution environment. C# 和 Java 均屬靜態類型,而這兩種語言都會將字串視為不可變的類型。Both C# and Java are statically-typed, and both languages treat strings as immutable types. 這兩種語言都會使用單一根目錄的類別階層。Both languages use a single-rooted class hierarchy. 就像 Java,C# 僅支援單一繼承,不允許全域方法。Like Java, C# supports only single inheritance and does not allow for global methods. 在這兩種語言中,會使用 new 關鍵字在堆積上建立物件,並於不再使用物件時進行記憶體回收。In both languages, objects are created on the heap using the new keyword, and objects are garbage-collected when they are no longer used. 這兩種語言都會使用 try/catch 語意,來提供正式的例外狀況處理支援。Both languages provide formal exception handling support with try/catch semantics. 這兩者都會提供執行緒管理和同步處理支援。Both provide thread management and synchronization support.

不過,Java 和 C# 之間有許多差異。However, there are many differences between Java and C#. 例如,For example:

  • JAVA (在 Android 上使用)不支援隱含類型區域變數(C#支援 var 關鍵字)。Java (as used on Android) does not support implicitly-typed local variables (C# supports the var keyword).

  • 在 Java 中,您只能依值傳遞參數,但在 C# 中,您可以傳址和依值方式進行傳遞In Java, you can pass parameters only by value, while in C# you can pass by reference as well as by value. (C# 提供 refout 關鍵字,用來以傳址方式傳遞參數;這些關鍵字在 Java 中沒有對等項目)。(C# provides the ref and out keywords for passing parameters by reference; there is no equivalent to these in Java).

  • Java 不支援像是 #define 的前置處理器指示詞。Java does not support preprocessor directives like #define.

  • Java 不支援不帶正負號的整數類型,而 C# 則能提供不帶正負號的整數類型,例如 ulonguintushortbyteJava does not support unsigned integer types, while C# provides unsigned integer types such as ulong, uint, ushort and byte.

  • Java 不支援運算子多載;但在 C# 中您可以多載運算子和轉換。Java does not support operator overloading; in C# you can overload operators and conversions.

  • 在 Java switch 陳述式中,程式碼可繼續進行下一個 switch 區段,但在 C# 中,每個 switch 區段的結尾都必須終止切換 (每個區段的結尾都必須使用 break 陳述式做結)。In a Java switch statement, code can fall through into the next switch section, but in C# the end of every switch section must terminate the switch (the end of each section must close with a break statement).

  • 在 Java 中,您可以使用 throws 關鍵字來指定方法擲回的例外狀況,但 C# 並沒有檢查例外狀況的概念 – C# 中不支援 throws 關鍵字。In Java, you specify the exceptions thrown by a method with the throws keyword, but C# has no concept of checked exceptions – the throws keyword is not supported in C#.

  • C# 支援 Language-Integrated Query (LINQ),讓您能夠使用保留字 fromselectwhere,以類似於資料庫查詢的方式撰寫對集合的查詢。C# supports Language-Integrated Query (LINQ), which lets you use the reserved words from, select, and where to write queries against collections in a way that is similar to database queries.

當然,在 C# 和 Java 之間還有更多本文未提及的差異。Of course, there are many more differences between C# and Java than can be covered in this article. 此外,Java 和 C# 都會持續進行改良 (例如,Java 8 (尚未存在於 Android 工具鏈中) 支援 C# 樣式的 Lambda 運算式),讓這些差異會隨著時間而改變。Also, both Java and C# continue to evolve (for example, Java 8, which is not yet in the Android toolchain, supports C#-style lambda expressions) so these differences will change over time. 此處僅概述不熟悉 Xamarin.Android 之 Java 開發人員目前所遇到的最重要差異。Only the most important differences currently encountered by Java developers new to Xamarin.Android are outlined here.

C# 會將許多重要功能帶入 Xamarin.Android,Android 上的 Java 開發人員目前仍無法立即使用這些功能。C# brings many key features to Xamarin.Android that are not currently readily available to Java developers on Android. 這些功能可協助您以較少的時間撰寫更好的程式碼:These features can help you to write better code in less time:

  • 屬性與C#的屬性系統 –,您可以安全且直接地存取成員變數,而不需要撰寫 setter 和 getter 方法。Properties – With C#'s property system, you can access member variables safely and directly without having to write setter and getter methods.

  • – 中的C# Lambda 運算式可以使用匿名方法(也稱為lambda),以更簡潔且更有效率地表達您的功能。Lambda Expressions – In C# you can use anonymous methods (also called lambdas) to express your functionality more succinctly and more efficiently. 您可以避免必須撰寫一次性使用之物件的額外負荷,並且可在不加入參數的情況下將本機狀態傳遞至方法。You can avoid the overhead of having to write one-time-use objects, and you can pass local state to a method without having to add parameters.

  • 事件處理– C#提供事件驅動程式設計的語言層級支援,其中的物件可以註冊,以便在發生感問題的事件時收到通知。Event Handling – C# provides language-level support for event-driven programming, where an object can register to be notified when an event of interest occurs. event 關鍵字會定義多點傳送廣播機制,讓發行者類別可用來通知事件訂閱者。The event keyword defines a multicast broadcast mechanism that a publisher class can use to notify event subscribers.

  • 非同步程式設計– 的非同步程式設計C#功能(async/await)讓應用程式保持回應。Asynchronous Programming – The asynchronous programming features of C# (async/await) keep apps responsive. 此功能的語言層級支援,可讓非同步程式設計容易實作且較不容易發生錯誤。The language-level support of this feature makes async programming easy to implement and less error-prone.

最後,Xamarin 可讓您透過名為「繫結」leverage existing Java assets的技術,運用現有的 Java 資產Finally, Xamarin allows you to leverage existing Java assets via a technology known as binding. 您可以使用 Xamarin 的自動繫結產生器,從 C# 呼叫現有的 Java 程式碼、架構和程式庫。You can call your existing Java code, frameworks, and libraries from C# by making use of Xamarin's automatic binding generators. 若要這樣做,您只需在 Java 中建立靜態程式庫,並透過繫結公開至 C#。To do this, you simply create a static library in Java and expose it to C# via a binding.

注意

Android 程式設計會使用 java 語言的特定版本,以支援所有 JAVA 7 功能和 java 8 的子集Android programming uses a specific version of the Java language that supports all Java 7 features and a subset of Java 8.

這個頁面上提到的部分功能(例如中C#的 var 關鍵字)適用于較新版本的 java (例如java 10中的var),但 Android 開發人員仍無法使用。Some features mentioned on this page (such as the var keyword in C#) are available in newer versions of Java (e.g. var in Java 10), but are still not available to Android developers.

從 JAVA 到C#開發Going from Java to C# development

下列各節將概述 C# 和 Java 之間的基本「入門」差異;更後面的小節則會描述這些語言之間的物件導向差異。The following sections outline the basic "getting started" differences between C# and Java; a later section describes the object-oriented differences between these languages.

程式庫與元件的比較Libraries vs. assemblies

Java 通常會在 .jar 檔案中封裝相關的類別。Java typically packages related classes in .jar files. 不過,在 C# 和 .NET 中,會將先行編譯程式碼的可重複使用位元封裝為「組件」,通常會封裝為 .dll 檔案。In C# and .NET, however, reusable bits of precompiled code are packaged into assemblies, which are typically packaged as .dll files. 組件是 C#/.NET 程式碼的一個部署單位,而每個組件通常會與一個 C# 專案相關聯。An assembly is a unit of deployment for C#/.NET code, and each assembly is typically associated with a C# project. 組件包含在執行階段進行 Just-In-Time 編譯的中繼程式碼 (IL)。Assemblies contain intermediate code (IL) that is just-in-time compiled at runtime.

如需組件的詳細資訊,請參閱組件與全域組件快取主題。For more information about assemblies, see the Assemblies and the Global Assembly Cache topic.

封裝與命名空間的比較Packages vs. namespaces

C# 會使用 namespace 關鍵字來將相關類型群組在一起;這類似於 Java 的 package 關鍵字。C# uses the namespace keyword to group related types together; this is similar to Java's package keyword. 一般而言,Xamarin.Android 應用程式將位於針對該應用程式建立的命名空間。Typically, a Xamarin.Android app will reside in a namespace created for that app. 例如,下列 C# 程式碼會針對氣象報告應用程式宣告 WeatherApp 命名空間包裝函式:For example, the following C# code declares the WeatherApp namespace wrapper for a weather-reporting app:

namespace WeatherApp
{
    ...

匯入類型Importing types

當您使用外部命名空間中定義的類型時,會使用 using 陳述式 (非常類似於 Java import 陳述式) 來匯入這些類型。When you make use of types defined in external namespaces, you import these types with a using statement (which is very similar to the Java import statement). 在 Java 中,您可能使用如下的陳述式來匯入單一類型:In Java, you might import a single type with a statement like the following:

import javax.swing.JButton

您可能使用如下的陳述式來匯入整個 Java 套件:You might import an entire Java package with a statement like this:

import javax.swing.*

C# using 陳述式的運作方式非常類似,但它可讓您匯入整個套件,而不需指定萬用字元。The C# using statement works in a very similar way, but it allows you to import an entire package without specifying a wildcard. 例如,您通常會在 Xamarin.Android 來源檔案開頭看到一連串的 using 陳述式,如此範例所示:For example, you will often see a series of using statements at the beginning of Xamarin.Android source files, as seen in this example:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Net;
using System.IO;
using System.Json;
using System.Threading.Tasks;

這些陳述式會從 SystemAndroid.AppAndroid.Content 等命名空間匯入功能。These statements import functionality from the System, Android.App, Android.Content, etc. namespaces.

泛型Generics

Java 和 C# 都支援「泛型」,其為可讓您在編譯時期插入不同類型的預留位置。Both Java and C# support generics, which are placeholders that let you plug in different types at compile time. 不過,泛型在 C# 中的運作方式稍有不同。However, generics work slightly differently in C#. 在 Java 中,類型清除 (英文) 讓類型資訊只能於編譯時期使用,而無法在執行階段使用。In Java, type erasure makes type information available only at compile time, but not at run time. 相反地,.NET Common Language Runtime (CLR) 提供泛型類型的明確支援,這表示 C# 可在執行階段存取類型資訊。By contrast, the .NET common language runtime (CLR) provides explicit support for generic types, which means that C# has access to type information at runtime. 在日常的 Xamarin.Android 開發中,此區別的重要性通常並不明顯,但如果您使用反映,將會依賴此功能,在執行階段存取類型資訊。In day-to-day Xamarin.Android development, the importance of this distinction is not often apparent, but if you are using reflection, you will depend on this feature to access type information at run time.

在 Xamarin.Android 中,您通常會看到用來取得版面配置控制項參考的泛型方法 FindViewByIdIn Xamarin.Android, you will often see the generic method FindViewById used to get a reference to a layout control. 這個方法可接受泛型類型參數來指定要查閱的控制項類型。This method accepts a generic type parameter that specifies the type of control to look up. 例如,For example:

TextView label = FindViewById<TextView> (Resource.Id.Label);

在此程式碼範例中,FindViewById 會取得 TextView 控制項 (定義於版面配置中) 的參考作為標籤,然後以 TextView 類型傳回它。In this code example, FindViewById gets a reference to the TextView control that is defined in the layout as Label, then returns it as a TextView type.

如需泛型的詳細資訊,請參閱泛型主題。For more information about generics, see the Generics topic. 請注意,在對於泛型 C# 類別的 Xamarin.Android 支援中有一些限制;如需詳細資訊,請參閱限制Note that there are some limitations in Xamarin.Android support for generic C# classes; for more information, see Limitations.

物件導向程式設計功能Object-oriented programming features

Java 和 C# 所使用的物件導向程式設計慣用語非常類似:Both Java and C# use very similar object-oriented programming idioms:

  • 所有類別最終都衍生自單一根物件 – 所有 Java 物件都衍生自 java.lang.Object,而所有 C# 物件都衍生自 System.ObjectAll classes are ultimately derived from a single root object – all Java objects derive from java.lang.Object, while all C# objects derive from System.Object.

  • 類別的執行個體均為參考類型。Instances of classes are reference types.

  • 存取執行個體的屬性和方法時,您會使用 "." 運算子。When you access the properties and methods of an instance, you use the "." operator.

  • 透過 new 運算子,在堆積上建立所有類別執行個體。All class instances are created on the heap via the new operator.

  • 由於這兩種語言都會使用記憶體回收,因此沒有可以明確釋放未使用物件的方法 (亦即,不像 C++ 中有 delete 關鍵字)。Because both languages use garbage collection, there is no way to explicitly release unused objects (i.e., there is not a delete keyword as there is in C++).

  • 您可以透過繼承擴充類別,而這兩種語言只允許每個類型一種基底類別。You can extend classes through inheritance, and both languages only allow a single base class per type.

  • 您可以定義介面,而類別可以繼承自 (即實作) 多個介面定義。You can define interfaces, and a class can inherit from (i.e., implement) multiple interface definitions.

不過,還有一些重要差異:However, there are also some important differences:

  • Java 有兩個功能強大但 C# 不支援的功能:匿名類別和內部類別Java has two powerful features that C# does not support: anonymous classes and inner classes. (不過,C# 允許巢串類別定義 – C# 的巢狀類別類似於 Java 的靜態巢狀類別)。(However, C# does allow nesting of class definitions – C#'s nested classes are like Java's static nested classes.)

  • C# 支援 C 樣式的結構類型 (struct),但 Java 不支援。C# supports C-style structure types (struct) while Java does not.

  • 在 C# 中,您可以使用 partial 關鍵字,在不同的來源檔案中實作類別定義。In C#, you can implement a class definition in separate source files by using the partial keyword.

  • C# 介面無法宣告欄位。C# interfaces cannot declare fields.

  • C# 使用 C++ 樣式的解構函式語法來表達完成項。C# uses C++-style destructor syntax to express finalizers. 此語法與 Java 的 finalize 方法不同,但語意幾乎完全相同The syntax is different from Java's finalize method, but the semantics are nearly the same. (請注意,在 C# 中,解構函式會自動呼叫基底類別解構函式 – 與明確呼叫 super.finalize 的 Java 相反)。(Note that in C#, destructors automatically call the base-class destructor – in contrast to Java where an explicit call to super.finalize is used.)

類別繼承Class inheritance

若要在 Java 中擴充類別,您可以使用 extends 關鍵字。To extend a class in Java, you use the extends keyword. 若要在 C# 中擴充類別,您可以使用冒號 (:) 來表示衍生。To extend a class in C#, you use a colon (:) to indicate derivation. 例如,在 Xamarin.Android 應用程式中,您通常會看到類似下列程式碼片段的類別衍生:For example, in Xamarin.Android apps, you will often see class derivations that resemble the following code fragment:

public class MainActivity : Activity
{
    ...

在此範例中,MainActivity 繼承自 Activity 類別。In this example, MainActivity inherits from the Activity class.

若要在 Java 中宣告對介面的支援,您可以使用 implements 關鍵字。To declare support for an interface in Java, you use the implements keyword. 不過,在 C# 中,您只需將介面名稱加入至要從中繼承之類別的清單即可,如下列程式碼片段所示:However, in C#, you simply add interface names to the list of classes to inherit from, as shown in this code fragment:

public class SensorsActivity : Activity, ISensorEventListener
{
    ...

在此範例中,SensorsActivity 繼承自 Activity,並實作 ISensorEventListener 介面中宣告的功能。In this example, SensorsActivity inherits from Activity and implements the functionality declared in the ISensorEventListener interface. 請注意,介面清單必須緊跟在基底類別後面 (否則您將收到編譯時期錯誤)。Note that the list of interfaces must come after the base class (or you will get a compile-time error). 依照慣例,C# 介面名稱前面會加上大寫 "I";這樣不需 implements 關鍵字,就能判斷哪些類別是介面。By convention, C# interface names are prepended with an upper-case "I"; this makes it possible to determine which classes are interfaces without requiring an implements keyword.

當您想要防止類別在中C#進一步分類時,您必須在類別名稱前面加上 sealed – 在 JAVA 中,然後在類別名稱前面加上 finalWhen you want to prevent a class from being further subclassed in C#, you precede the class name with sealed – in Java, you precede the class name with final.

如需 C# 類別定義的詳細資訊,請參閱類別繼承主題。For more about C# class definitions, see the Classes and Inheritance topics.

屬性Properties

在 Java 中,更動子方法 (setter) 和檢查方法 (getter) 通常可用來控制如何對類別成員進行變更,同時隱藏並保護這些成員,以免受到外部程式碼干擾。In Java, mutator methods (setters) and inspector methods (getters) are often used to control how changes are made to class members while hiding and protecting these members from outside code. 例如,Android TextView 類別提供 getTextsetText 方法。For example, the Android TextView class provides getText and setText methods. C# 提供類似但更直接的機制,也就是「屬性」。C# provides a similar but more direct mechanism known as properties. C# 類別的使用者可使用他們存取欄位相同的方式來存取屬性,但每次存取實際上會產生對呼叫端而言是透明的方法呼叫。Users of a C# class can access a property in the same way as they would access a field, but each access actually results in a method call that is transparent to the caller. 這個「隱藏」方法可以實作設定其他值、執行轉換或變更物件狀態之類的副作用。This "under the covers" method can implement side effects such as setting other values, performing conversions, or changing object state.

屬性通常用於存取和修改 UI (使用者介面) 物件成員。Properties are often used for accessing and modifying UI (user interface) object members. 例如,For example:

int width = rulerView.MeasuredWidth;
int height = rulerView.MeasuredHeight;
...
rulerView.DrawingCacheEnabled = true;

在此範例中,藉由存取 rulerView 物件的 MeasuredWidthMeasuredHeight 屬性,從該物件中讀取寬度和高度值。In this example, width and height values are read from the rulerView object by accessing its MeasuredWidth and MeasuredHeight properties. 讀取這些屬性時,會在幕後擷取來自其相關聯 (但隱藏) 之欄位的值,然後傳回呼叫端。When these properties are read, values from their associated (but hidden) field values are fetched behind the scenes and returned to the caller. rulerView 物件可能會以一種測量單位 (例如像素) 來儲存寬度和高度值,並在存取 MeasuredWidthMeasuredHeight 屬性時,將這些值即時轉換為不同的測量單位 (例如公釐)。The rulerView object may store width and height values in one unit of measurement (say, pixels) and convert these values on-the-fly to a different unit of measurement (say, millimeters) when the MeasuredWidth and MeasuredHeight properties are accessed.

rulerView 物件也有一個稱為 DrawingCacheEnabled 的屬性 – 範例程式碼會將此屬性設定為 true,以便在 rulerView中啟用繪圖快取。The rulerView object also has a property called DrawingCacheEnabled – the example code sets this property to true to enable the drawing cache in rulerView. 在幕後,會使用新值來更新相關聯的隱藏欄位,而且可能會修改 rulerView 狀態的其他層面。Behind the scenes, an associated hidden field is updated with the new value, and possibly other aspects of rulerView state are modified. 例如,將 DrawingCacheEnabled 設為 false 時,rulerView 可能也會清除物件中已累積的任何繪圖快取資訊。For example, when DrawingCacheEnabled is set to false, rulerView may also erase any drawing cache information already accumulated in the object.

屬性的存取權可以是讀取/寫入、唯讀或唯寫的權限。Access to properties can be read/write, read-only, or write-only. 此外,您還能使用不同的存取修飾詞進行讀取和寫入。Also, you can use different access modifiers for reading and writing. 例如,您可以定義具有公用讀取權限但具有私用寫入權限的屬性。For example, you can define a property that has public read access but private write access.

如需 C# 屬性的詳細資訊,請參閱屬性主題。For more information about C# properties, see the Properties topic.

呼叫基類方法Calling base class methods

若要在 C# 中呼叫基底類別建構函式,您可以使用冒號 (:),後面接著 base 關鍵字和初始設定式清單;這個 base 建構函式呼叫會放在衍生的建構函式參數清單正後方。To call a base-class constructor in C#, you use a colon (:) followed by the base keyword and an initializer list; this base constructor call is placed immediately after the derived constructor parameter list. 在進入衍生的建構函式時呼叫基底類別建構函式;編譯器會將對基底建構函式的呼叫插入至方法主體的開頭處。The base-class constructor is called on entry to the derived constructor; the compiler inserts the call to the base constructor at the start of the method body. 下列程式碼片段將說明如何從 Xamarin.Android 應用程式中衍生的建構函式呼叫基底建構函式:The following code fragment illustrates a base constructor called from a derived constructor in a Xamarin.Android app:

public class PictureLayout : ViewGroup
{
    ...
    public PictureLayout (Context context)
           : base (context)
    {
        ...
    }
    ...
}

在此範例中,PictureLayout 類別衍生自 ViewGroup 類別。In this example, the PictureLayout class is derived from the ViewGroup class. 範例中所示的 PictureLayout 建構函式會接受 context 引數,並透過 ViewGroup 呼叫來將其傳遞給 base(context) 建構函式。The PictureLayout constructor shown in this example accepts a context argument and passes it to the ViewGroup constructor via the base(context) call.

若要在 C# 中呼叫基底類別方法,使用 base 關鍵字。To call a base-class method in C#, use the base keyword. 例如,Xamarin.Android 應用程式通常會進行基底方法的呼叫,如下所示:For example, Xamarin.Android apps often make calls to base methods as shown here:

public class MainActivity : Activity
{
    ...
    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

在此情況下,衍生類別 (OnCreate) 所定義的 MainActivity 方法會呼叫基底類別 (OnCreate) 的 Activity 方法。In this case, the OnCreate method defined by the derived class (MainActivity) calls the OnCreate method of the base class (Activity).

存取修飾詞Access modifiers

Java 和 C# 均支援 publicprivateprotected 存取修飾詞。Java and C# both support the public, private, and protected access modifiers. 不過,C# 支援兩個額外的存取修飾詞:However, C# supports two additional access modifiers:

  • internal – 類別成員只能在目前的元件中存取。internal – The class member is accessible only within the current assembly.

  • protected internal – 類別成員可在定義元件、定義類別和衍生類別(元件內部和外部的衍生類別都有存取權)內進行存取。protected internal – The class member is accessible within the defining assembly, the defining class, and derived classes (derived classes both inside and outside the assembly have access).

如需 C# 存取修飾詞的詳細資訊,請參閱存取修飾詞主題。For more information about C# access modifiers, see the Access Modifiers topic.

虛擬和覆寫方法Virtual and override methods

Java 和 C# 均支援「多型」,這是以相同方式處理相關物件的能力。Both Java and C# support polymorphism, the ability to treat related objects in the same manner. 在這兩種語言中,您可以使用基底類別參考來參考衍生類別的物件,而衍生類別的方法可以覆寫其基底類別的方法。In both languages, you can use a base-class reference to refer to a derived-class object, and the methods of a derived class can override the methods of its base classes. 這兩種語言均具備「虛擬」方法的概念,此為設計來由衍生類別中的方法所取代之基底類別中的方法。Both languages have the concept of a virtual method, a method in a base class that is designed to be replaced by a method in a derived class. 就像 Java,C# 支援 abstract 類別和方法。Like Java, C# supports abstract classes and methods.

不過,在 Java 和 C# 之間有一些如何宣告虛擬方法和覆寫它們的差異:However, there are some differences between Java and C# in how you declare virtual methods and override them:

  • 在 C# 中,方法預設為非虛擬的。In C#, methods are non-virtual by default. 父類別必須使用 virtual 關鍵字,明確地標示要覆寫哪些方法。Parent classes must explicitly label which methods are to be overridden by using the virtual keyword. 相反地,Java 中的所有方法依預設都是虛擬方法。By contrast, all methods in Java are virtual methods by default.

  • 若要在 C# 中避免方法遭到覆寫,只需捨棄 virtual 關鍵字即可。To prevent a method from being overridden in C#, you simply leave off the virtual keyword. 相反地,Java 會使用 final 關鍵字,來將方法標示為「不允許覆寫」。By contrast, Java uses the final keyword to mark a method with "override is not allowed."

  • C# 衍生類別必須使用 override 關鍵字,明確指出要覆寫的虛擬基底類別方法。C# derived classes must use the override keyword to explicitly indicate that a virtual base-class method is being overridden.

如需對於多型的 C# 支援詳細資訊,請參閱多型主題。For more information about C#'s support for polymorphism, see the Polymorphism topic.

Lambda 運算式Lambda expressions

C# 讓您能夠建立「關閉」:內嵌的匿名方法,可存取要將它們封閉在其中的方法狀態。C# makes it possible to create closures: inline, anonymous methods that can access the state of the method in which they are enclosed. 使用 Lambda 運算式,您可以撰寫較少的程式碼,來實作可能已在 Java 中使用更多行程式碼實作的相同功能。Using lambda expressions, you can write fewer lines of code to implement the same functionality that you might have implemented in Java with many more lines of code.

Lambda 運算式可讓您略過建立一次性使用的類別或匿名類別 (就像您在 Java 中所做的) 時所涉及的額外儀式 – 相反地,您只需撰寫內嵌方法程式碼的商務邏輯。Lambda expressions make it possible for you to skip the extra ceremony involved in creating a one-time-use class or anonymous class as you would in Java – instead, you can just write the business logic of your method code inline. 此外,由於 Lambda 具備周圍方法中變數的存取權,因此,您不需建立一份很長的參數清單來將狀態傳遞至方法程式碼。Also, because lambdas have access to the variables in the surrounding method, you don't have to create a long parameter list to pass state to your method code.

在 C# 中,會使用 => 運算子來建立 Lambda 運算式,如下所示:In C#, lambda expressions are created with the => operator as shown here:

(arg1, arg2, ...) => {
    // implementation code
};

在 Xamarin.Android 中,Lambda 運算式通常會用來定義事件處理常式。In Xamarin.Android, lambda expressions are often used for defining event handlers. 例如,For example:

button.Click += (sender, args) => {
    clickCount += 1;    // access variable in surrounding code
    button.Text = string.Format ("Clicked {0} times.", clickCount);
};

在此範例中,Lambda 運算式程式碼 (大括號內的程式碼) 會遞增點按計數,並更新 button 文字來顯示點按計數。In this example, the lambda expression code (the code within the curly braces) increments a click count and updates the button text to display the click count. 這個 Lambda 運算式會使用 button 物件註冊,以作為每次點選按鈕時要呼叫的 Click 事件處理常式This lambda expression is registered with the button object as a click event handler to be called whenever the button is tapped. (以下會詳細說明事件處理常式)。在這個簡單的範例中,lambda 運算式程式碼不會使用 senderargs 參數,但 lambda 運算式中必須要有它們,才能符合事件註冊的方法簽章需求。(Event handlers are explained in more detail below.) In this simple example, the sender and args parameters are not used by the lambda expression code, but they are required in the lambda expression to meet the method signature requirements for event registration. 背後的原理是,C# 編譯器會將 Lambda 運算式轉譯為匿名方法,每次發生按鈕 Click 事件時即會呼叫此方法。Under the hood, the C# compiler translates the lambda expression into an anonymous method that is called whenever button click events take place.

如需 C# 和 Lambda 運算式的詳細資訊,請參閱 Lambda 運算式主題。For more information about C# and lambda expressions, see the Lambda Expressions topic.

事件處理Event handling

「事件」是在該物件發生感興趣的事情時,用來通知已註冊訂閱者的方式。An event is a way for an object to notify registered subscribers when something interesting happens to that object. 不同於在 Java 中,訂閱者通常會實作包含回呼方法的 Listener 介面,C# 會透過「委派」提供事件處理的語言層級支援。Unlike in Java, where a subscriber typically implements a Listener interface that contains a callback method, C# provides language-level support for event handling through delegates. 「委派」類似物件導向的類型安全函式指標 – 它會封裝物件參考和方法語彙基元。A delegate is like an object-oriented type-safe function pointer – it encapsulates an object reference and a method token. 如果用戶端物件想要訂閱事件,它會建立委派,並將委派傳遞至通知物件。If a client object wants to subscribe to an event, it creates a delegate and passes the delegate to the notifying object. 發生事件時,通知物件會叫用委派物件所表示的方法,通知事件的訂閱用戶端物件。When the event occurs, the notifying object invokes the method represented by the delegate object, notifying the subscribing client object of the event. 在 C# 中,事件處理常式基本上就是透過委派叫用的方法。In C#, event handlers are essentially nothing more than methods that are invoked through delegates.

如需委派的詳細資訊,請參閱委派主題。For more information about delegates, see the Delegates topic.

在 C# 中,事件是「多點傳送」;也就是,在事件發生時,可以通知多個接聽程式。In C#, events are multicast; that is, more than one listener can be notified when an event takes place. 當您考慮 Java 和 C# 事件註冊之間的語法差異時,可觀察到此差異。This difference is observed when you consider the syntactical differences between Java and C# event registration. 在 Java 中,您會呼叫 SetXXXListener 來註冊事件通知;在 C# 中,您會使用 += 運算子,藉由將委派「加入」至事件接聽程式清單來註冊事件通知。In Java you call SetXXXListener to register for event notifications; in C# you use the += operator to register for event notifications by "adding" your delegate to the list of event listeners. 在 Java 中,您會呼叫 SetXXXListener 來取消註冊,而在 C# 中,您會使用 -=,從接聽程式清單中「減去」您的委派。In Java, you call SetXXXListener to unregister, while in C# you use the -= to "subtract" your delegate from the list of listeners.

在 Xamarin.Android 中,當使用者對 UI 控制項執行某個動作時,通常會使用事件來通知物件。In Xamarin.Android, events are often used for notifying objects when a user does something to a UI control. 一般來說,UI 控制項必須具備使用 event 關鍵字定義的成員;您會將委派連結至這些成員,以訂閱來自該 UI 控制項的事件。Normally, a UI control will have members that are defined using the event keyword; you attach your delegates to these members to subscribe to events from that UI control.

訂閱事件:To subscribe to an event:

  1. 建立委派物件,其會參考您想要在事件發生時叫用的方法。Create a delegate object that refers to the method that you want to be invoked when the event occurs.

  2. 使用 += 運算子,將委派連結至您要訂閱的事件。Use the += operator to attach your delegate to the event you are subscribing to.

下列範例會定義委派 (明確使用 delegate 關鍵字) 來訂閱按鈕 Click。The following example defines a delegate (with an explicit use of the delegate keyword) to subscribe to button clicks. 這個按鈕 Click 處理常式會啟動新的活動:This button-click handler starts a new activity:

startActivityButton.Click += delegate {
    Intent intent = new Intent (this, typeof (MyActivity));
    StartActivity (intent);
};

不過,您也可以使用 Lambda 運算式來註冊事件,完全略過 delegate 關鍵字。However, you also can use a lambda expression to register for events, skipping the delegate keyword altogether. 例如,For example:

startActivityButton.Click += (sender, e) => {
    Intent intent = new Intent (this, typeof (MyActivity));
    StartActivity (intent);
};

在此範例中,startActivityButton 物件的事件會預期含有特定方法簽章的委派:一個接受傳送者和事件引數並傳回 void 的委派。In this example, the startActivityButton object has an event that expects a delegate with a certain method signature: one that accepts sender and event arguments and returns void. 不過,由於我們不想特意明確地定義這類委派或它的方法,因此,會使用 (sender, e) 宣告方法的簽章,並使用 Lambda 運算式來實作事件處理常式的主體。However, because we don't want to go to the trouble to explicitly define such a delegate or its method, we declare the signature of the method with (sender, e) and use a lambda expression to implement the body of the event handler. 請注意,我們必須宣告這個參數清單,即使並未使用 sendere 參數也一樣。Note that we have to declare this parameter list even though we aren't using the sender and e parameters.

請務必記住,您可以取消訂閱委派 (透過 -= 運算子),但無法取消訂閱 Lambda 運算式 – 嘗試這樣做,可能會導致記憶體流失。It is important to remember that you can unsubscribe a delegate (via the -= operator), but you cannot unsubscribe a lambda expression – attempting to do so can cause memory leaks. 只有在您的處理常式不會取消訂閱事件時,才能使用 Lambda 形式的事件註冊。Use the lambda form of event registration only when your handler will not unsubscribe from the event.

一般而言,Lambda 運算式可用來宣告 Xamarin.Android 程式碼中的事件處理常式。Typically, lambda expressions are used to declare event handlers in Xamarin.Android code. 這個宣告事件處理常式的簡略方式一開始可能看似神秘,不過,它可以在您寫入和讀取程式碼時節省大量時間。This shorthand way to declare event handlers may seem cryptic at first, but it saves an enormous amount of time when you are writing and reading code. 隨著熟悉度的增加,您會變得習慣辨識此模式 (Xamarin.Android 程式碼中經常發生),而您會花費更多時間來思考應用程式的商務邏輯,並減少費力完成語法額外負荷的時間。With increasing familiarity, you become accustomed to recognizing this pattern (which occurs frequently in Xamarin.Android code), and you spend more time thinking about the business logic of your application and less time wading through syntactical overhead.

非同步程式設計Asynchronous programming

「非同步程式設計」可增進應用程式的整體回應能力。Asynchronous programming is a way to improve the overall responsiveness of your application. 當應用程式的某個部分遭到漫長作業封鎖時,非同步程式設計功能可讓應用程式程式碼的剩餘部分繼續執行。Asynchronous programming features make it possible for the rest of your app code to continue running while some part of your app is blocked by a lengthy operation. 存取 Web、處理影像,以及讀取/寫入檔案,都是會導致整個應用程式看起來像凍結般 (如果它不會以非同步方式寫入) 的作業範例。Accessing the web, processing images, and reading/writing files are examples of operations that can cause an entire app to appear to freeze up if it is not written asynchronously.

C# 包含透過 asyncawait 關鍵字進行非同步程式設計的語言層級支援。C# includes language-level support for asynchronous programming via the async and await keywords. 這些語言功能讓您能夠非常容易地撰寫程式碼來執行長時間執行的工作,而不會封鎖應用程式的主執行緒。These language features make it very easy to write code that performs long-running tasks without blocking the main thread of your application. 簡單來說,您可以在方法上使用 async 關鍵字,來指出方法中的程式碼會以非同步方式執行,而且不會封鎖呼叫端的執行緒。Briefly, you use the async keyword on a method to indicate that the code in the method is to run asynchronously and not block the caller's thread. 您可以在呼叫使用 await 標記的方法時,使用 async 關鍵字。You use the await keyword when you call methods that are marked with async. 編譯器會將 await 解譯為要將您的方法執行移至背景執行緒 (會將工作傳回給呼叫端) 所在的點。The compiler interprets the await as the point where your method execution is to be moved to a background thread (a task is returned to the caller). 完成此工作時,程式碼的執行會在程式碼中 await 點的呼叫端執行緒上繼續執行,並傳回 async 呼叫的結果。When this task completes, execution of the code resumes on the caller's thread at the await point in your code, returning the results of the async call. 依照慣例,以非同步方式執行的方法會在其名稱結尾加上 Async 後置字元。By convention, methods that run asynchronously have Async suffixed to their names.

在 Xamarin.Android 應用程式中,當長時間執行的作業在背景工作中執行時,通常會使用 asyncawait 來釋放 UI 執行緒,讓它可以回應使用者輸入 (例如,點選 [取消] 按鈕)。In Xamarin.Android applications, async and await are typically used to free up the UI thread so that it can respond to user input (such as the tapping of a Cancel button) while a long-running operation takes place in a background task.

在下列範例中,按鈕 Click 事件處理常式會導致非同步作業從 Web 下載影像:In the following example, a button click event handler causes an asynchronous operation to download an image from the web:

downloadButton.Click += downloadAsync;
...
async void downloadAsync(object sender, System.EventArgs e)
{
    webClient = new WebClient ();
    var url = new Uri ("http://photojournal.jpl.nasa.gov/jpeg/PIA15416.jpg");
    byte[] bytes = null;

    bytes = await webClient.DownloadDataTaskAsync(url);

    // display the downloaded image ...

在此範例中,當使用者按一下 downloadButton 控制項時,downloadAsync 事件處理常式會建立 WebClient 物件和 Uri 物件,以從指定的 URL 擷取影像。In this example, when the user clicks the downloadButton control, the downloadAsync event handler creates a WebClient object and a Uri object to fetch an image from the specifed URL. 接下來,它會搭配這個 URL 呼叫 WebClient 物件的 DownloadDataTaskAsync 方法來擷取影像。Next, it calls the WebClient object's DownloadDataTaskAsync method with this URL to retrieve the image.

請注意,downloadAsync 的方法宣告會以 async 關鍵字開始,表示它將以非同步方式執行並傳回工作。Notice that the method declaration of downloadAsync is prefaced by the async keyword to indicate that it will run asynchronously and return a task. 也請注意,對 DownloadDataTaskAsync 的呼叫會以 await 關鍵字開始。Also note that the call to DownloadDataTaskAsync is preceded by the await keyword. 應用程式會將事件處理常式的執行 (從 await 出現點開始) 移至背景執行緒,直到 DownloadDataTaskAsync 完成並傳回為止。The app moves the execution of the event handler (starting at the point where await appears) to a background thread until DownloadDataTaskAsync completes and returns. 同時,應用程式的 UI 執行緒仍然可以回應使用者輸入,並引發其他控制項的事件處理常式。Meanwhile, the app's UI thread can still respond to user input and fire event handlers for the other controls. DownloadDataTaskAsync 完成 (這可能需要幾秒鐘) 時,執行就會從將 bytes 變數設為對 DownloadDataTaskAsync 之呼叫的結果處繼續,而事件處理常式程式碼的其餘部分會顯示呼叫端 (UI) 執行緒上下載的影像。When DownloadDataTaskAsync completes (which may take several seconds), execution resumes where the bytes variable is set to the result of the call to DownloadDataTaskAsync, and the remainder of the event handler code displays the downloaded image on the caller's (UI) thread.

如需 C# 中 async/await 的簡介,請參閱使用 Async 和 Await 進行非同步程式設計主題。For an introduction to async/await in C#, see the Asynchronous Programming with Async and Await topic. 如需非同步程式設計功能的 Xamarin 支援詳細資訊,請參閱非同步支援概觀For more information about Xamarin support of asynchronous programming features, see Async Support Overview.

關鍵字差異Keyword differences

Java 中使用的許多語言關鍵字也會在 C# 中使用。Many language keywords used in Java are also used in C#. 另外有些 Java 關鍵字在 C# 中具有相等但以不同方式命名的對等項目,如下表所示:There are also a number of Java keywords that have an equivalent but differently-named counterpart in C#, as listed in this table:

JavaJava C#C# 描述Description
boolean boolbool 用來宣告布林值的真偽。Used for declaring the boolean values true and false.
extends : 優先要從中繼承的類別和介面。Precedes the class and interfaces to inherit from.
implements : 優先要從中繼承的類別和介面。Precedes the class and interfaces to inherit from.
import usingusing 從命名空間匯入類型,也可用來建立命名空間別名。Imports types from a namespace, also used for creating a namespace alias.
final sealedsealed 防止類別衍生;防止方法和屬性在衍生類別中遭到覆寫。Prevents class derivation; prevents methods and properties from being overridden in derived classes.
instanceof isis 評估物件是否可與指定的類型相容。Evaluates whether an object is compatible with a given type.
native externextern 宣告在外部實作的方法。Declares a method that is implemented externally.
package namespacenamespace 宣告一組相關物件的範圍。Declares a scope for a related set of objects.
T... params Tparams T 指定採用可變數目之引數的方法參數。Specifies a method parameter that takes a variable number of arguments.
super basebase 用來存取衍生類別中父類別的成員。Used to access members of the parent class from within a derived class.
synchronized locklock 包裝含有鎖定取得和釋放的重要程式碼區段。Wraps a critical section of code with lock acquisition and release.

此外,有許多對C#而言是唯一的關鍵字,而且在 Android 上使用的 JAVA 沒有對應的。Also, there are many keywords that are unique to C# and have no counterpart in the Java used on Android. Xamarin.Android 程式碼通常會使用下列 C# 關鍵字 (當您透過範例程式碼 (英文) 讀取時非常適合參考此表格):Xamarin.Android code often makes use of the following C# keywords (this table is useful to refer to when you are reading through Xamarin.Android sample code):

C#C# 描述Description
asas 在可相容的參考類型或可為 Null 的類型之間執行轉換。Performs conversions between compatible reference types or nullable types.
asyncasync 指定方法或 Lambda 運算式為非同步。Specifies that a method or lambda expression is asynchronous.
awaitawait 暫停執行方法,直到工作完成為止。Suspends the execution of a method until a task completes.
bytebyte 不帶正負號的 8 位元整數類型。Unsigned 8-bit integer type.
delegatedelegate 用來封裝方法或匿名方法。Used to encapsulate a method or anonymous method.
enumenum 宣告列舉,一組具名常數。Declares an enumeration, a set of named constants.
eventevent 宣告發行者類別中的事件。Declares an event in a publisher class.
fixedfixed 防止變數遭到重新配置。Prevents a variable from being relocated.
get 定義可擷取屬性值的存取子方法。Defines an accessor method that retrieves the value of a property.
inin 讓參數能夠接受泛型介面中較少衍生的類型。Enables a parameter to accept a less derived type in a generic interface.
objectobject .NET Framework 中 Object 型別的別名。An alias for the Object type in the .NET framework.
outout 參數修飾詞或泛型類型參數宣告。Parameter modifier or generic type parameter declaration.
overrideoverride 擴充或修改繼承成員的實作。Extends or modifies the implementation of an inherited member.
partialpartial 宣告要分割成多個檔案的定義,或從它的實作分割方法定義。Declares a definition to be split into multiple files, or splits a method definition from its implementation.
readonlyreadonly 宣告類別成員只能在宣告期間或透過類別建構函式加以指派。Declares that a class member can be assigned only at declaration time or by the class constructor.
refref 導致引數會以傳址方式傳遞,而不是依值傳遞。Causes an argument to be passed by reference rather than by value.
setset 定義可設定屬性值的存取子方法。Defines an accessor method that sets the value of a property.
stringstring .NET Framework 中 String 型別的別名。Alias for the String type in the .NET framework.
structstruct 封裝相關變數群組的實值類型。A value type that encapsulates a group of related variables.
typeoftypeof 取得物件類型。Obtains the type of an object.
varvar 宣告隱含類型的區域變數。Declares an implicitly-typed local variable.
valuevalue 參考用戶端程式碼想要指派給屬性的值。References the value that client code wants to assign to a property.
virtualvirtual 允許在衍生類別中覆寫方法。Allows a method to be overridden in a derived class.

與現有的 java 程式碼交互操作Interoperating with existing java code

如果您目前具有不想轉換為 C# 的 Java 功能,您可以透過下列兩種技術,在 Xamarin.Android 應用程式中重複使用現有的 Java 程式庫:If you have existing Java functionality that you do not want to convert to C#, you can reuse your existing Java libraries in Xamarin.Android applications via two techniques:

  • 建立 java系結程式庫 – 使用這種方法,您可以使用 Xamarin C#工具來產生有關 java 類型的包裝函式。Create a Java Bindings Library – Using this approach, you use Xamarin tools to generate C# wrappers around Java types. 這些包裝函式稱為「繫結」。These wrappers are called bindings. 如此一來,Xamarin.Android 應用程式就可藉由呼叫這些包裝函式來使用 .jar 檔案。As a result, your Xamarin.Android application can use your .jar file by calling into these wrappers.

  • JAVA原生介面JAVA 原生介面(JNI)是一種架構,可讓C#應用程式呼叫或由 java 程式碼呼叫。Java Native Interface – The Java Native Interface (JNI) is a framework that makes it possible for C# apps to call or be called by Java code.

如需這些技術的詳細資訊,請參閱 Java 整合概觀For more information about these techniques, see Java Integration Overview.

進一步閱讀Further reading

MSDN C# 程式設計手冊是開始學習 C# 程式設計語言的絕佳方法,而您可以使用 C# 參考來查閱特定的 C# 語言功能。The MSDN C# Programming Guide is a great way to get started in learning the C# programming language, and you can use the C# Reference to look up particular C# language features.

就像所具備的 Java 知識對於 Java 類別庫的熟悉程度,至少要與了解 Java 語言一樣,對於 C# 的實務知識需要對 .NET Framework 有某種程度的熟悉。In the same way that Java knowledge is at least as much about familiarity with the Java class libraries as knowing the Java language, practical knowledge of C# requires some familiarity with the .NET framework. Microsoft 的移至 C# 和 .NET Framework,適用於 Java 開發人員 (英文) 學習封包是從 Java 觀點深入了解 .NET Framework (同時還能更深入了解 C#) 的好方法。Microsoft's Moving to C# and the .NET Framework, for Java Developers learning packet is a good way to learn more about the .NET framework from a Java perspective (while gaining a deeper understanding of C#).

當您準備好要在 C# 中處理第一個 Xamarin.Android 專案時,我們的 Hello, Android 系列可協助您建置第一個 Xamarin.Android 應用程式,並進一步了解使用 Xamarin 進行 Android 應用程式開發的基本知識。When you are ready to tackle your first Xamarin.Android project in C#, our Hello, Android series can help you build your first Xamarin.Android application and further advance your understanding of the fundamentals of Android application development with Xamarin.

摘要Summary

本文從 Java 開發人員的觀點介紹了 Xamarin.Android C# 程式設計環境。This article provided an introduction to the Xamarin.Android C# programming environment from a Java developer's perspective. 它指出 C# 和 Java 之間的相似性,同時說明它們的實際差異。It pointed out the similarities between C# and Java while explaining their practical differences. 它介紹了組件和命名空間、說明如何匯入外部類型,並提供存取修飾詞、泛型、類別衍生、呼叫基底類別方法、方法覆寫,以及事件處理中差異的概觀。It introduced assemblies and namespaces, explained how to import external types, and provided an overview of the differences in access modifiers, generics, class derivation, calling base-class methods, method overriding, and event handling. 它介紹了無法在 Java 中使用的 C# 功能,例如,屬性、async/await 非同步程式設計、Lambda、C# 委派,以及 C# 事件處理系統。It introduced C# features that are not available in Java, such as properties, async/await asynchronous programming, lambdas, C# delegates, and the C# event handling system. 其中包含重要 C# 關鍵字的表格、說明如何與現有的 Java 程式庫相互操作,並提供相關文件的連結以取得進一步研究。It included tables of important C# keywords, explained how to interoperate with existing Java libraries, and provided links to related documentation for further study.