47

Jesse Liberty の Learning C# ブックの中で、彼は「あるタイプのオブジェクトを別のタイプのオブジェクトに変換できます。これをキャストと呼びます」と述べています。

以下のコードから生成された IL を調べると、キャストされた割り当てが変換された割り当てと同じことをしていないことがはっきりとわかります。前者では、ボックス化/ボックス化解除が発生していることがわかります。後者では、convert メソッドの呼び出しを確認できます。

結局、それはばかげた意味の違いにすぎないことはわかっていますが、変換するための別の単語をキャストしているだけです。意地悪をするつもりはありませんが、これに関する誰かの直感には興味がありません。意見はここでは考慮しません。キャストと変換が同じものであるかどうかを確認または否定する決定的な参照を誰かが指摘できますか?

    object x;
    int y;

    x = 4;

    y = ( int )x;

    y = Convert.ToInt32( x );

ありがとうございました

rp

明示的/暗黙的に関するマットのコメントの後に追加されたメモ:

暗黙的/明示的な違いはないと思います。私が投稿したコードでは、どちらの場合も変更が明示的です。暗黙的な変換は、int に short を割り当てるときに発生するものです。

Sklivvz へのメモ:

私は、ジェシー・リバティの(それ以外の場合は、通常は明快で明快な)言葉遣いが緩いという私の疑いが正しいことを確認したかったのです。ジェシー・リバティは言葉遣いが少し緩いなと思いました。キャストはオブジェクト階層でルーティングされることを理解しています。つまり、整数から文字列にキャストすることはできませんが、System.Exception から派生したカスタム例外から System.Exception にキャストすることはできます。

ただし、int から文字列にキャストしようとすると、値を「変換」できなかったとコンパイラが通知するのは興味深いことです。思ったよりもジェシーが正解かも!

4

11 に答える 11

29

絶対違う!

Convert は、「可能な限りの手段」で Int32 を取得しようとします。キャストは何もしません。キャストを使用すると、変換せずにオブジェクトを Int として扱うようにコンパイラに指示します。

オブジェクトが Int32 または Int32 へのキャスト演算子を持つ別のクラス (float など) であることが (設計により) わかっている場合は、常にキャストを使用する必要があります。

Convert は、String または他のクラスと共に使用する必要があります。

これを試して

static void Main(string[] args)
{
    long l = long.MaxValue;

    Console.WriteLine(l);

    byte b = (byte) l;

    Console.WriteLine(b);

    b = Convert.ToByte(l);

    Console.WriteLine(b);

}

結果:

9223372036854775807

255

未処理の例外:

System.OverflowException: 値が System.Convert.ToByte (Int64 値) [0x00000] の Byte.MaxValue より大きいか、/home/marco の Test.Main (System.String[] args) [0x00019] の Byte.MinValue より小さい/develop/test/Exceptions.cs:15

于 2008-09-27T17:03:44.660 に答える
18

簡単な答えは次のとおりです。

値型の場合、キャストには、それを別の型に純粋に変換することが含まれます。例えば:

float f = 1.5f;
int i = (int) f; // Conversion

キャスト式が箱から出されたとき、結果は (それが機能すると仮定して)通常、箱の中にあったものと同じ型の単なるコピーです。ただし、例外があります。ボックス化された int から列挙型 (基になる型が int の) にボックス化を解除したり、その逆を行うことができます。同様に、ボックス化された int から Nullable<int> にボックス化を解除できます。

キャスト式がある参照型から別の参照型への変換であり、ユーザー定義の変換が含まれていない場合、オブジェクト自体に関する限り、変換は行われず、参照の型のみが「変更」されます。参照自体ではなく、値が考慮されます (以前と同じビットになります)。例えば:

object o = "hello";
string x = (string) o; // No data is "converted"; x and o refer to the same object

ユーザー定義の変換が関係する場合、通常は異なるオブジェクト/値を返す必要があります。たとえば、独自の型の文字列への変換を定義できますが、これは確かに独自のオブジェクトと同じデータにはなりません。(もちろん、すでにオブジェクトから参照されている既存の文字列である可能性があります。)私の経験では、ユーザー定義の変換は通常、参照型ではなく値型の間に存在するため、これが問題になることはめったにありません。

これらはすべて、仕様の観点からは変換としてカウントされますが、オブジェクトを別の型のオブジェクトに変換するとはみなされませこれは、ジェシー・リバティが用語にルーズであることが原因ではないかと思います。ちょうど読んでいる C# 3.0 のプログラミングで気づいたことです。

それはすべてをカバーしていますか?

于 2008-09-27T17:21:33.197 に答える
7

私が見た最良の説明は以下のとおりで、その後にソースへのリンクが続きます。

「... 真実はそれよりも少し複雑です。.NET は、いわば A 地点から B 地点に到達するための 3 つの方法を提供します。

まず、暗黙のキャストがあります。これは、割り当て以上のことを行う必要がないキャストです。

int i = 5;
double d = i;

これらは「拡大変換」とも呼ばれ、.NET ではキャスト演算子を使用せずに実行できます。これは、変換によって情報が失われることがないためです。double の有効な値の可能な範囲は、int の有効な値の範囲を含み、そのため、この割り当てを行うことは決してありません。その後、ランタイムが int 値から数桁の値を落としたことに恐ろしいことに気付くことはありません。参照型の場合、暗黙のキャストの背後にあるルールは、キャストが InvalidCastException をスローできないということです。キャストが常に有効であることは、コンパイラにとって明らかです。

独自の型に対して新しい暗黙のキャスト演算子を作成できます (つまり、愚かであれば、すべての規則を破る暗黙のキャストを作成できます)。基本的な経験則では、暗黙的なキャストには、遷移で情報が失われる可能性を含めることはできません。

この変換では、基になる表現変更されていることに注意してください。double は int とはまったく異なる方法で表現されます。

2 番目の種類の変換は、明示的なキャストです。情報が失われる可能性がある場合、またはキャストが無効で InvalidCastException がスローされる可能性がある場合は、明示的なキャストが必要です。

double d = 1.5;
int i = (int)d;

ここでは、明らかに情報が失われます。i はキャスト後に 1 になるため、0.5 は失われます。これは「ナローイング」変換とも呼ばれ、コンパイラでは、情報が失われる可能性があることはわかっているが気にしないことを示すために、明示的なキャスト (int) を含める必要があります。

同様に、参照型の場合、実行時にキャストが有効でない可能性がある状況では、コンパイラは明示的なキャストを必要とします。リスクがあることはわかっているが、自分が何をしているのかはわかっているというシグナルです。

3 番目の種類の変換は、設計者が明示的なキャストさえ提供しなかったような表現の根本的な変更を伴うものです。変換を行うために、メソッドを呼び出す必要があります。

string s = "15";
int i = Convert.ToInt32(s);

ここでメソッド呼び出しを絶対に必要とするものは何もないことに注意してください。暗黙的および明示的なキャストもメソッド呼び出しです (これが独自の方法です)。設計者は、文字列を int に変換する明示的なキャスト演算子を簡単に作成できたはずです。メソッドを呼び出すという要件は、言語の基本的な要件ではなく、スタイル上の選択です。

文体の推論は次のようになります: String から int への変換は複雑な変換であり、ひどくうまくいかない可能性がたくさんあります:

string s = "The quick brown fox";
int i = Convert.ToInt32(s);

このように、メソッド呼び出しは、読むべきドキュメントを提供し、これが単なるクイック キャスト以上のものであるという広範なヒントを提供します。

独自の型 (特に独自の値型) を設計する場合、キャスト演算子と変換関数を作成することを決定する場合があります。「暗黙的キャスト」、「明示的キャスト」、および「変換関数」の領域を分割する線は少しぼやけているため、人によって、何をすべきかについて異なる決定を下す可能性があります。情報の損失、および例外や無効なデータの可能性を念頭に置いてください。それが決定に役立つはずです。」

  • ブルース・ウッド、2005 年 11 月 16 日

http://bytes.com/forum/post1068532-4.html

于 2008-09-27T17:12:01.550 に答える
2

キャスティングには参照が含まれます

List<int> myList = new List<int>();
//up-cast
IEnumerable<int> myEnumerable = (IEnumerable<int>) myList;
//down-cast
List<int> myOtherList = (List<int>) myEnumerable;

要素の追加など、myList に対する操作は、myEnumerable と myOtherList に反映されることに注意してください。これは、それらがすべて同じインスタンスへの (さまざまな型の) 参照であるためです。

アップキャストは安全です。ダウンキャストは、プログラマーが型を間違えた場合に実行時エラーを生成する可能性があります。安全なダウンキャストは、この回答の範囲を超えています。

変換にはインスタンスが含まれます

List<int> myList = new List<int>();
int[] myArray = myList.ToArray();

myList は、myArray を生成するために使用されます。これは非破壊的な変換です (この操作の後、myList は完全に正常に動作します)。また、要素の追加など、myList に対する操作は myArray に反映されないことに注意してください。これは、それらが完全に別個のインスタンスであるためです。

decimal w = 1.1m;
int x = (int)w;

実際には変換である C# のキャスト構文を使用する操作があります。

于 2008-09-27T17:40:12.857 に答える
1

セマンティクスはさておき、簡単なテストでは、それらが同等ではないことが示されています!
彼らは異なる方法でタスクを実行します (または、異なるタスクを実行する可能性があります)。

x=-2.5 (int)x=-2 Convert.ToInt32(x)=-2
x=-1.5 (int)x=-1 Convert.ToInt32(x)=-2
x=-0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 1.5 (int)x= 1 Convert.ToInt32(x)= 2
x= 2.5 (int)x= 2 Convert.ToInt32(x)= 2

x=-1.5x=1.5ケースに注意してください。

于 2008-10-29T13:49:36.467 に答える
0

キャストは、オブジェクトが実際にその型である (またはその型の基本型/インターフェイスを持っている) ことをコンパイラ/インタプリタに伝えています。これは、コンパイラー/インターパーターが仕事をするのではなく、実際に文字列を解析し、数値に変換するための計算を行う関数である変換と比較して、かなり高速です。

于 2008-09-27T17:04:41.037 に答える
0

キャストとは常に、オブジェクトのデータ型を変更することを意味します。これは、たとえば、浮動小数点値を整数値に変換するか、ビットを再解釈することによって実行できます。これは通常、言語でサポートされている (読み取り: コンパイラでサポートされている) 操作です。

「変換」という用語はキャストに使用されることもありますが、通常は何らかのライブラリまたは独自のコードによって行われ、必ずしもキャストと同じ結果になるとは限りません。たとえば、インペリアルの重量値をメートル法の重量に変換すると、同じデータ型 (浮動小数点数など) のままで、別の数値になる場合があります。別の典型的な例は、度からラジアンへの変換です。

于 2008-09-27T17:06:24.607 に答える
0

言語/フレームワークにとらわれない話し方では、ある型またはクラスから別の型またはクラスへの変換は、キャストと呼ばれます。最初の 4 行が示すように、これは .NET にも当てはまります。

object x;
int y;

x = 4;

y = ( int )x;

C および C に似た言語 (C# など) は、(newtype)somevarキャストに構文を使用します。たとえば、VB.NET には、このための明示的な組み込み関数があります。最後の行は次のように記述されます。

y = CInt(x)

または、より複雑なタイプの場合:

y = CType(x, newtype)

「C」は明らかに「キャスト」の略です。

ただし、.NET にもそのConvert()機能があります。これは (上記の 2 つとは異なり) 組み込みの言語機能ではなく、フレームワークの 1 つです。これは、必ずしも .NET と一緒に使用されるとは限らない言語を使用すると、より明確になります。これらの言語には、独自のキャスト手段がある可能性が非常に高くなりますが、追加するのは .NET ですConvert()

マットが言うように、動作の違いConvert()はより明確です。コンパイラに単に とy同等の整数として扱うように指示するのではなく、整数クラスに適した方法で変更し、結果を代入するようxに具体的に指示しています。xy

あなたの特定のケースでは、キャストは「ボックス化解除」と呼ばれるものを行いますConvert()が、実際には整数値を取得します。結果は同じように見えますが、Keith が説明する微妙な違いがあります。

于 2008-09-27T17:12:28.010 に答える
0

MCTS Self-Paced Training Kit (Exam 70-536): Microsoft® .NE​​T Framework 2.0—Application Development Foundationの第 1 章、レッスン 4 の 55 ページの「明示的な変換の方法」というタイトルの表 1-7 によると、確かにそれらの違い。

System.Convertは言語に依存せず、「System.IConvertible インターフェイスを実装する型の間」を変換します。

(型) キャスト演算子は、 「変換演算子を定義する型の間」を変換するC# 固有の言語機能です。

さらに、カスタム変換を実装する場合、アドバイスはそれらの間で異なります。

上記のレッスンの 56 ~ 57 ページの「カスタム型で変換を実装する方法」というタイトルのセクションによると、変換演算子 (キャスト) は数値型間の変換を単純化するためのものですが、Convert() はカルチャ固有の変換を有効にします

どの手法を選択するかは、実行する変換のタイプによって異なります。

  • 変換演算子を定義して、数値型間の縮小変換と拡大変換を簡素化します。

  • System.IConvertibleを実装して、System.Convert による変換を有効にします。この手法を使用して、カルチャ固有の変換を有効にします。

  • ...

キャスト変換演算子は IConvertible インターフェイスとは別に実装されているため、Convert() は必ずしもキャストの別の名前であるとは限らないことは明らかです。(しかし、一貫性を確保するために、ある実装が他の実装を参照する場所を想像することはできます)。

于 2008-09-27T18:17:43.420 に答える
-2

キャストは基本的に、オブジェクトが新しい型であると「ふりをする」ようにランタイムに指示するだけです。オブジェクトを実際に変換または変更することはありません。

ただし、Convert は、ある型を別の型に変換する操作を実行します。

例として:

char caster = '5';
Console.WriteLine((int)caster);

これらのステートメントの出力は 53 になります。これは、ランタイムがビット パターンを調べてそれを int として処理するだけであるためです。最終的に得られるのは、数字の 5 ではなく、文字 5 の ASCII 値です。

ただし、Convert.ToInt32(caster) を使用すると、実際に文字列を読み取って正しく変更するため、5 が返されます。(基本的に、ASCII 値 53 が実際には整数値 5 であることを認識しています。)

于 2008-09-27T17:16:10.090 に答える
-4

違いは、変換が暗黙的か明示的かです。最初のものはキャストで、2 つ目は変換する関数へのより明示的な呼び出しです。彼らはおそらく、同じことをさまざまな方法で行っています。

于 2008-09-27T17:01:07.210 に答える