質問

Jesse LibertyのLearning C#ブックでは、彼は<!> quot;あるタイプのオブジェクトを別のタイプのオブジェクトに変換できると言っています。これはキャストと呼ばれます。<!> quot;

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

最終的には、それは単なる愚かな意味の違いかもしれないことを知っていますが、変換するための別の単語をキャストしています。意地悪をするつもりはありませんが、私はこれに関する誰の直感にも興味がありません。意見はここでは数えません!キャストと変換が同じものであるかどうかを確認または拒否する決定的な参照を誰かが指すことができますか?

    object x;
    int y;

    x = 4;

    y = ( int )x;

    y = Convert.ToInt32( x );

ありがとう

rp

明示的/暗黙的についてのマットのコメントの後に追加されたメモ:

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

Sklivvzへの注意:

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

しかし、興味深いのは、intから文字列にキャストしようとすると、コンパイラが<!> quot; convert <!> quot;値。たぶん、ジェシーは私が思っていたよりも正確です!

役に立ちましたか?

解決

単純な答えは次のとおりです。依存します。

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

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

キャスト式のボックス化が解除されると、結果は(それが機能すると仮定して)通常、ボックス内の同じタイプのコピーになります。ただし、例外があります-ボックス化されたintから列挙型(基になる型のint)にボックス化を解除できます。同様に、ボックス化されたintからNullable <!> lt; int <!> gt;にボックス化解除できます。

キャスト式がある参照型から別の参照型への変換であり、ユーザー定義の変換が含まれていない場合、オブジェクト自体に関する限り、変換は行われません-参照 <! > quot; changes <!> quot; -そしてそれは、参照自体(以前と同じビットになります)ではなく、実際に値が考慮される方法にすぎません。例:

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

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

これらはすべて、仕様に関しては変換としてカウントされますが、すべてがオブジェクトを異なるタイプのオブジェクトに変換するとカウントされるわけではありません。これはJesse Libertyの専門用語がゆるい場合だと思います-プログラミングC#3.0で、今読んでいることに気づきました。

それですべてがカバーされますか?

他のヒント

絶対に違う!

Convertは、<!> quot; anyは可能です<!> quot;でInt32を取得しようとします。キャストは何もしません。キャストでは、オブジェクトを変換せずにIntとして扱うようコンパイラーに指示しています。

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

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:値は   Byte.MaxValueより大きいか、それ以下   Byte.MinValueより   System.Convert.ToByte(Int64値)   [0x00000] Test.Mainで   (System.String [] args)[0x00019] in   /home/marco/develop/test/Exceptions.cs:15

私が見た中で最も良い説明は以下にあり、ソースへのリンクが続きます:

<!> quot; ...真実はそれよりも少し複雑です。 .NETが提供する ポイントAからポイントBに到達する3つの方法。

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

int i = 5;
double d = i;

これらは、<!> quot;拡大変換<!> quotとも呼ばれます。 .NETでは次のことができます 決して失うことはないので、キャスト演算子なしでそれらを実行します それを行う情報:doubleの有効な値の可能な範囲 intの有効な値の範囲と、次に有効な値の範囲を含むため、 あなたは決してこの割り当てを行ってからあなたに発見するつもりはありません ランタイムがint値から数桁を落としたという恐怖。にとって 参照型、暗黙のキャストの背後にあるルールは、キャスト InvalidCastExceptionをスローすることはありません。コンパイラーにとって明らかです。 キャストが常に有効であること。

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

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

2番目の種類の変換は、明示的なキャストです。明示的なキャストは 情報を失う可能性がある場所で必要な場合、または キャストが有効ではない可能性があるため、スローする可能性があります InvalidCastException:

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

ここでは、明らかに情報を失うことになります。 キャストするため、0.5が失われます。これは<!> quot; narrowing <!> quotとも呼ばれます。 変換、およびコンパイラは明示的なキャストを含める必要があります (int)はい、情報が失われる可能性があることを知っていますが、 気にしません。

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

3番目の種類の変換は、このような根本的な変更を伴うものです デザイナーが明示的にさえ提供しなかったという表現で キャスト:変換を行うためにメソッドを呼び出します:

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

ここでメソッド呼び出しを絶対に必要とするものは何もないことに注意してください。 暗黙的キャストと明示的キャストもメソッド呼び出しです(これがあなたの作る方法です) あなた自身の)。デザイナーは非常に簡単に明示的な 文字列をintに変換するキャスト演算子。その要件 メソッドを呼び出すことは、根本的というよりもスタイルの選択です 言語の要件。

文体的な推論は次のようになります:String-to-intは 物事が進む機会がたくさんある複雑な変換 恐ろしく間違っている:

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

このように、メソッド呼び出しは読むべきドキュメントを提供し、 これは単なるキャストではないことを示唆しています。

独自の型(特に独自の値型)を設計するとき、 キャスト演算子と変換関数を作成することがあります。台詞 <!> quot; implicit cast <!> quot;、<!> quot; explicit cast <!> quot ;、および<!> quot; conversion function <!> quot; 領土は少しぼやけているので、人によって違います 何がどうあるべきかの決定。覚えておいてください 情報の損失、例外および無効なデータの可能性、および それはあなたが決めるのに役立つはずです。<!> quot;

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

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

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

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#のキャスト構文を使用する操作は実際のコンバージョン

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

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.5およびx=1.5のケースに注意してください。

キャストは、オブジェクトが実際にそのタイプであること(またはそのタイプのベースタイプ/インターフェースを持っていること)をコンパイラ/インタプリタに伝えています。コンパイラー/インターパーターがジョブを実行するのではなく、文字列を解析して数値に変換する数学を実行する関数である変換と比較して、実行するのは非常に高速です。

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

用語<!> quot; converting <!> quot;キャストに使用されることもありますが、通常は何らかのライブラリまたは独自のコードによって実行され、必ずしもキャストと同じになるとは限りません。たとえば、インペリアルウェイト値があり、それをメトリックウェイトに変換する場合、同じデータ型(たとえば、float)のままであるが、異なる数値になる場合があります。別の典型的な例は、度からラジアンへの変換です。

言語/フレームワークに依存しない話し方では、あるタイプまたはクラスから別のタイプまたはクラスへの変換は、キャスティングとして知られています。最初の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と必ずしも一緒に使用される必要のない言語を使用する場合に明らかになります。それらはまだ独自のキャスト手段を持っている可能性が高いですが、yを追加するのは.NETです。

Mattが言うように、振る舞いの違いはxがより明示的であることです。 <=>を<=>に相当する整数として扱うようコンパイラーに単に指示するのではなく、整数クラス then に適した方法で<=>を変更するよう具体的に指示しています結果を<=>に割り当てます。

特定のケースでは、キャストは「アンボックス化」と呼ばれる処理を行いますが、<=>は実際に整数値を取得します。結果は同じように見えますが、微妙な違いがありますキースによる説明

表1-7によると、<!> quot;明示的な変換の方法<!> quot; MCTS Self-Paced Training Kit(試験70-536)の第1章レッスン4の55ページ:Microsoft <!>#174; .NET Framework 2.0 <!>#8212;アプリケーション開発財団、それらの間には確かに違いがあります。

System.Convert は言語に依存せず、<!> quot; System.IConvertibleインターフェイス。<!> quot;

を実装する型の間で変換します。

(type)キャスト演算子は、 C#固有の言語機能であり、<!> quot; 変換演算子を定義する型の間で変換します。 <!>引用;

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

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

  

選択する手法は、実行する変換の種類によって異なります。

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

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

  •   
  • ...

  •   

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

変数をキャストおよび変換する他の方法を忘れないでください:as、Parse、TryParse 互換性のあるデータ型間の暗黙的なキャストも同様です。

このサイトには、ほとんどのメソッドの出力の良いサンプルがあります: C#ボクシングとアンボクシング

これらのサンプル変数が与えられた場合:

int i = 3, x;
long l;
string s = "5";

基本的に、2つの互換性のある型の間で暗黙的なキャストを行うことができます:

l = i;

ボックス化解除または as キーワードを使用した明示的なキャスト:

s = (string)i;
//or
s = i as string;

System.Convertのメソッドを使用した明示的な変換:

i = System.Convert.ToInt32(s);

定義されたデータ型のメソッドを使用した明示的な変換:

i = int.Parse(s);
i = int.TryParse(s, x);

変数のインスタンスのメソッドを使用した明示的な変換:

s = i.ToString();

キャスティングは、互換性のある2つのタイプ間で割り当てを行うための単なる方法であると思います。

変換は、互換性のない型から別の型に値を明示的にコピーする必要があり、悪の強制

MSDNでも役立つ情報:キャストと型変換

キャスティングは基本的に、ランタイムに<!> quot; pretend <!> quot;を伝えるだけです。オブジェクトは新しいタイプです。オブジェクトを実際に変換または変更することはありません。

ただし、

Convertは、あるタイプを別のタイプに変換する操作を実行します。

例:

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

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

ただし、Convert.ToInt32(caster)を使用する場合は、実際に文字列を読み取り、正しく変更するため、5を取得します。 (本質的に、ASCII値53は実際には整数値5であることを知っています。)

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top