C SharpとJavaの比較
C#、Java共に、ジェネリクスの共変性と反変性 (covariance and contravariance) を持つ。ただしC#における共変性・反変性のサポートはバージョン4.0以降である。
C#では、型定義側で共変性outあるいは反変性inを指定し、利用側では変性の指定を行わない。なお、C#の値型は不変 (invariant) であり、共変性・反変性は適用されない。
Javaでは、型定義側では変性の指定を行わず、利用側で共変性extendsあるいは反変性superを指定する。 Javaではさらに、上限と下限のいずれも指定しないワイルドカード?による型引数の指定が可能である。以下にJava 8の例を示す。
↑ 型 (C# リファレンス) | Microsoft Docs
↑ 値型 (C# リファレンス) | Microsoft Docs
↑ データ型 (C# と Java の比較) | Microsoft Docs
↑ Built-in types table (C# Reference) | Microsoft Docs
↑ Type.IsPrimitive Property (System) | Microsoft Docs
↑ Parameterless struct constructors - C# 10.0 draft specifications | Microsoft Learn
↑ C# 7.0 の新機能 - C# ガイド | Microsoft Docs
これによってプリミティブ型(もしくは値型)は参照型のサブセットとみなすことができる。値型は仮想メソッドテーブルを持たず、したがってそのままでは多態性を利用できないが、C#においては、ボックス化によって値型で多態性を利用することが可能である(例えばobject型のToString()メソッドをオーバーライドすることができる)。C#では数値リテラルもオブジェクトであり、たとえば42.ToString()のようにint型のリテラルからメソッドを呼び出すことも可能である。Javaではこのような用途のためにプリミティブ型をラップするクラスが別に定義される。すなわち、42.toString()のようなインスタンスメソッド呼び出しでなくInteger.toString(42)のような静的メソッド呼び出しが必要になる。もう一つの相違点として、Javaではジェネリクスにおいてこのような型を多用するため、暗黙的なボックス化解除が可能になっている(C#ではボックス化せずにジェネリクスを利用できる)。このような変換はnullポインタ例外を発生する可能性があるが、Javaではそれがコード上で明白ではない。
C#では、structキーワードによって構造体を定義することができる。構造体にはフィールドやメソッド、プロパティなどの任意のメンバーを定義できる。引数を持たないコンストラクタ(デフォルトコンストラクタ)をプログラマが定義することはできないが、一つ以上の引数を持つパラメータ化されたコンストラクタを定義することはできる。
Scala
Kotlin
Groovy