14

コードを Java から C# に手動で変換しており、(私が呼んでいるもの) プリミティブ型に苦労しています (たとえば、Do autoboxing and unboxing behavior in Java and C# を参照)。回答から、double(C#) とDouble(C#) は同等であり、double(C#) はコンテナでも使用できることを理解しています。たとえば、ディクショナリのキーとして使用できます。ただし、double(Java) は HashMap のようなコンテナーでは使用できないため、(Java) に自動ボックス化されDoubleます。

  1. (C#) はプリミティブですかdouble、それともオブジェクトですか?
  2. doubleそれがプリミティブである場合、 (Java)とは異なる動作をする理由は何ですか?

double(C#) にしないと null に設定できませんnullable

  1. (C#)は(Java)double?と同等ですか? Doubleそれらは両方ともオブジェクトと呼ばれますか?

(「ファーストクラス オブジェクト」という用語の使用は、この議論で役に立ちますか?)

4

3 に答える 3

17

C# と Java の両方にプリミティブ (または「値」) 型があります: int、double、float など...

ただし、この後、C# と Java は分裂する傾向にあります。

Java には、すべてのプリミティブ型(Java では小さな有限集合) のラッパー クラス型があり、それらをオブジェクトとして扱うことができます。double/Doubleint/Integerbool/Booleanなど。これらのラッパー型は参照型 (読み: クラス) であり、そのnullような型付き式/変数に割り当てる有効な値です。Java の最近のバージョン (1.5/5+) では、プリミティブから対応するラッパーへの暗黙的な強制が追加されています。

// Java
Boolean b = true; // implicit conversion boolean -> Boolean (Java 5+)
Boolean b = null; // okay, can assign null to a reference type
boolean n = null; // WRONG - null is not a boolean!

C# はこのような直接ラッピングを提供しません1 - 一部には、C# が構造体を介して値の型の無限のセットをサポートするためです。むしろ、C# はラッパー型の導入によって "null 許容値型" を処理します。さらに、C# は Java と同様に、値型から への暗黙的な変換を行いますが、T 自体は「null 許容型ではない」という制限があります。Nullable<T>TNullable<T>

// C#
Nullable<bool> b = true; // implicit conversion bool -> bool?
bool? b = true;          // short type syntax, implicit conversion
bool? b = null;          // okay, can assign null as a Nullable-type
bool b = null;           // WRONG - null is not a bool

Nullable<T>も値型であるため、値が「スタック上」にあるかどうかについては、標準の構造規則に従うことに注意してください。

コメントに応じて:

Nullable が値型であると、参照型のメモリ オーバーヘッドを回避できるため、特定のケースではよりコンパクトなメモリ フットプリントを持つことができます。ただし、値がnullかどうかを覚えておく必要があるため、Nullableでない型よりも多くのメモリが必要です。アラインメントの問題と VM の実装に応じて、これは「完全な」オブジェクトよりも大幅に小さい場合とそうでない場合があります。また、C#/CLR の値は具体化されているため、実行する必要があるリフティング操作を検討してください。

// C#
object x = null;
x = (bool?)true;
(x as bool?).Value // true

記事Java Tip 130: Do you know your data size? 参照型のメモリ消費について (Java で) 話します。注意すべきことの 1 つは、JVM には、各プリミティブ型とオブジェクト用に 1 つずつ、内部的に特殊化されたバージョンの配列があることです (ただし、この記事には誤解を招く記述が含まれていることに注意してください)。オブジェクト (対プリミティブ) が余分なメモリ オーバーヘッドとバイト アラインメントの問題をどのように発生させるかに注意してください。ただし、C# は、型の最適化された配列のケースと、それ自体が単なる構造型 (または「プリミティブ」) であるNullable<T>ため、JVM が持つ限られた特殊なケースを拡張できます。Nullable<T>

ただし、オブジェクトは、可変スロットで「参照」を維持するために小さな固定サイズしか必要としません。Nullable<LargeStruct>一方、タイプの可変スロットには、 LargeStruct+Nullable(スロット自体がヒープ上にある場合もあります) ためのスペースが必要です。C# の概念: 値と参照型を参照してください。上記の「リフティング」の例で変数の型がどのようになっているかに注意してくださいobject:objectは C# の「ルート型」(参照型と値型の両方の親) であり、特殊な値型ではありません。


1 C# 言語は、 「使いやすい小文字」の型名へのアクセスを許可するプリミティブ/共通型のエイリアスの固定セットをサポートしています。たとえば、doubleは のエイリアスでSystem.Doubleあり、intは のエイリアスですSystem.Int32Double別の型がスコープにインポートされてdoubleいない限り、DoubleC# で同じ型を参照します。特に理由がない限り、エイリアスを使用することをお勧めします。

于 2009-10-21T01:58:04.550 に答える
10

Nullable<double>double?C#の(aka )はJavaのaと同じではありません。Double

Javaが自動ボクシング/アンボクシングを行う前は、プリミティブとファーストクラスオブジェクトを手動で変換する必要がありました。

Double dblObj = new Double(2.0);
double dblPrim = dblObj.doubleValue();

これが変更されたJava1.5では、次のことができます。

Double dblObj = 2.0;
double dblPrim = dblObj;

また、Javaは、上記の例を自動的にミラーリングするコードを挿入します。

C#は、「プリミティブ」型(CLRが値型と呼ぶもの)の数に制限がないため、異なります。これらは、値のセマンティクスを使用して、ほとんどJavaのプリミティブのように動作します。structキーワードを使用して新しい値型を作成できます。C#には、すべての値型の自動ボクシング/アンボクシングがあり、すべての値型をから派生させObjectます。

したがって、任意のオブジェクト参照を使用する値型(のようなdouble)を使用できます(たとえば、のキーとしてDictionary)。必要に応じてボックス化されるか、直接使用されます。(C#のGenerics実装は、ほとんどの状況でボクシングを回避するのに十分です。)

于 2009-10-21T00:07:45.537 に答える
1

C#では、オブジェクトを分離する最良の方法は、プリミティブ(ints、boolsなど)や「参照型」(クラスなど)のような「値型」を使用することです。

于 2009-10-21T00:09:51.010 に答える