C SharpとJavaの比較
Javaは言語仕様をシンプルに保つため、また乱用による難読化を防ぐため、ユーザー定義の演算子オーバーロードをサポートしていない。一方でコードの書きやすさおよび直感性は犠牲になっている。
C#は表記法の多くの点でJavaよりも多機能である。演算子多重定義やユーザー定義キャストなど、それらの多くはC++プログラマによって既に親しまれているものである。
C#はインデクサ(C++のoperator[]に相当)をサポートする。インデクサの定義構文はプロパティと似ているが、this[]という名前をもち、一つ以上の引数(インデックス)を持つ点が異なる。インデクサを定義する際、インデックスには任意の型を使用することができる。
C#は(論理的一貫性を保つための制限はあるものの)ユーザー定義の演算子オーバーロードをサポートしており、注意深く使用すれば簡潔で可読性の高いコードを記述することができる。
また、C#では明示的メンバ実装 (Explicit Member Implementation) が可能である。これによって、インターフェイスメソッドの実装とクラス自身のメソッドの実装とを分離することができ、また同じシグネチャ(名前および引数の数と型の順序)を持つメソッドが異なるインターフェイスにそれぞれ存在した場合に、インターフェイス名を指定して区別することでそれらの実装を別々に行うことができる。
C#には、統合言語クエリの為の拡張されたキーワード群が存在し、ソースコード上でSQL構文に似たクエリを直接記述することができる。このキーワード群は構文糖として機能し、決められた拡張メソッド呼び出しに展開される。
統合言語クエリの拡張メソッド群は、コレクションに対するさまざまな集合演算が実装されており、このような演算をロジックで記述することなく、簡単に操作することができる。 また、ラムダ式から式ツリー(Expressionクラス)のインスタンスを生成することが出来るため、この機能を使用してデータベースへのクエリ発行・収集を、タイプセーフ性を失うことなく直接的に行うことができる(LINQ to SQL、LINQ to Entitiesなど)。 Javaでは、このようなクエリ構文を直接サポートしない。Java 8ではC#のLINQメソッド構文に近い記述が可能となるStream APIとラムダ式がサポートされた。
列挙型の値を組み合わせるためには列挙セットクラスを使用する必要がある。Javaの列挙型では、値によって異なるメソッドの実装が可能である。JavaとC#はいずれも列挙型を文字列に変換することができるが、Javaにおいてはこの変換をカスタマイズすることができる。また、Javaの列挙型は任意のインターフェイスを実装することができる。
プリミティブ型(あるいは値型)は参照型(クラス)とは異なり、インスタンスはヒープ領域ではなくスタックに置かれる。また、(フィールドとして、あるいはボックス化された状態で)クラスの一部になることも、配列の要素になることも可能である。クラスのインスタンスはメモリ上で間接的に参照される必要があるが、プリミティブ型(あるいは値型)はその必要がない。プログラマの視点からは、C#の値型は軽量なクラスとみなせる。しかし、プリミティブ型(あるいは値型)には前述のように多数の制限がある。値型は通常nullの値をとることができないが、.NET Framework 2.0でnull許容型 (System.Nullable) が導入され、C#でも擬似的にnull値を取り得る値型が利用可能となった。
型そのものをコード上で表現するメタデータ型(メタクラス)として、Javaではjava.lang.Classを、C#ではSystem.Typeを利用する。これらはいずれもリフレクションやイントロスペクションで重要な役割を果たす。
このため、既存コードのインターフェイスがC言語形式関数でありさえすれば、余分なレイヤーは必要にならない。P/Invokeは(Win32やPOSIXなどの)手続き型APIにはほぼ完全にアクセスすることができるが、C++クラスライブラリへの直接的なアクセスはきわめて困難である。そのほか、C++/CLI言語を介することで、C#とC/C++間の相互運用を行なうことも可能である。またCOM相互運用により、コード資産を相互に利用することも可能である。
C#は通常の型チェックなどのCLRの安全のための機能を無効にし、ポインタ変数を利用することができる。この時、プログラマはコードをunsafeキーワードでマークする必要がある。JNI、P/Invoke、unsafeコードはどれも同様に「危険な」機能であり、セキュリティホールやアプリケーションの不安定性につながる恐れがある。unsafeコードがP/InvokeやJNIに対して優れている点は、アンマネージコードを呼び出すことなくC#の機能内でタスクを完結できる点である。unsafeコードを含むアセンブリはコンパイル時にそのように明示的に指定する必要がある。これにより、実行環境は危険な可能性があるコードであるということを実行する前に知ることができる。