- - PR -
キャストについて
投稿者 | 投稿内容 | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2009-01-09 17:38
この場合は、CInt/CType使っても、Math.〜使っても、Convert.ToInt32のどれ使っても同じ結果になりますね。 単なる好みの話になってしまいますが、私ならConvert.ToInt32(decimal)使いますかね。 (小数部0なので、特に意味はないですがCInt/CType、Convert.ToInt32(decimal)のどの場合も 銀行型丸めとして処理されます。) ※このパターンにCType使う場合、CType(変数, Int32)とすると思いますが、 これはCIntの呼び出しとまったく同じです。
CType演算子は知っているけど、使ったことがない状態で詳しくないですが、 CType 関数 で見ても、CType演算子とCType関数が関連しているようなので、 こちらはご指摘の通りのように思います。 #ここはちょっと自信なし。他の方法があったらご指摘お願いします。>ご覧の方。 | ||||||||||||||||||||||||
|
投稿日時: 2009-01-09 22:25
なんというか…思い切り盲点を突かれた感じですw そうですね…変換と考えれば Convert.ToInt32 でもいいし、Decimal.ToInt32 でもいいですね。 何と言うか、C# だと単純に (int) と書いちゃうところなので「キャスト」だと思いこんでて、VB でキャストっていうと DirectCast か CType しかないと思いこんでいました。 今後は ToInt32 を使うことにします。ありがとうございました。
私も自分でキャストを実装する機会はあまりないのですが、例えば System.Drawing の Point から Size には変換が実装されています。 Point.op_Explicit メソッド こういう変換を行うときは、やはり CType しかないですよね。Point.op_Explicit ってそのまま書く手もありますが、それも気持ち悪いですし。 | ||||||||||||||||||||||||
|
投稿日時: 2009-01-10 10:34
(利用規約違反のため削除いたしました。@ITクラブメンバーシップセンター)
| ||||||||||||||||||||||||
|
投稿日時: 2009-01-13 11:02
テッテさん、よねKENさん
キャストと変換について、今まで特に意識することなく使用していました。 以下のようにまとめましたが、合っていますでしょうか? また型変換とキャストでは型変換の方がパフォーマンスがよいのでしょうか? そうではなくCtypeやCintは内部で何をしているか分からないから使用しない方がよいのでしょうか? 例1) Object型の変数に入っているDouble型の値を○○○してDouble型の変数に入れる。 1、これは明示的な型変換(キャスト) Dim o As Object = 123.123 Dim d As Double = DirectCast(o, Double) 例2) Int32型の変数に入っているInt32型の値を○○○してDouble型の変数に入れる。 1、これは暗黙的な型変換 Dim i As Integer = 123 Dim d As Double = i 2、これは明示的な型変換(キャスト) Dim i As Integer = 123 Dim d As Double = Ctype(i,Double) 3、これは型変換 Dim i As Integer = 123 d = Convert.ToDouble(i) 例3)Double型の変数に入っているDouble型の値を○○○してInt32型の変数に入れる。 1、これは明示的な型変換(キャスト) Dim d As Double = Math.Ceiling(123.123) Dim i As Integer = Ctype(d,Integer) 2、これは型変換 Dim d As Double = Math.Ceiling(123.123) Dim i As Integer = Convert.ToInt32(d) 例4) String型の変数に入っているString型の値"123"を○○○してInt32型の変数に123を入れる。 1、これは明示的な型変換(キャスト) ※おすすめではない Dim s As String = "123" Dim i As Integer = Ctype(s,Integer) 2、これは型変換 Dim s As String = "123" Dim i As Integer = Integer.Parse(s) 例5) String型の変数に入っているString型の値"123"(全角)を○○○してInt32型の変数に123を入れる。 1、これは明示的な型変換(キャスト) ※おすすめではない Dim s As String = "123" Dim i As Integer = Ctype(s,Integer) 2、これは型変換 Dim s As String = Strings.StrConv("123", VbStrConv.Narrow) Dim i As Integer =Integer.Parse(s) 例6) Decimal型の変数に入っている値が、情報を失うことなく Int32 に変換できるとわかっている場合に、それを○○○してInt32型の変数に入れる。 1、これは明示的な型変換(キャスト) Dim d As Double = 123.000 Dim i As Integer = Ctype(d,Integer) 2、これは型変換 Dim d As Double = 123.000 Dim i As Integer = Convert.ToInt32(d) 例7) 型Aから型Bへの縮小変換が定義されていていて、型Aの変数に入っている型Aの値を○○○して型Bの変数に入れる。(演算子がオーバーロードされているという意味です。) これはCtypeをつかわざるを得ない。 (※このような処理が必要になったことは今まで経験したことがありません。) このようにみるとCtypeを使わなければならない場面はかぎられてくるのですね。 私が最初に質問した回答は以下のようになりましたが、合っていますでしょうか? 1、テキストボックスに入力されている数字(カンマ区切りの数字文字列または全角数字を含む)を数値にキャストする場合はどのキャストを使うのでしょうか? 一旦半角に変換し、Parseを使用する。 Dim s As String = Strings.StrConv(Me.TextBox1.Text, VbStrConv.Narrow) Dim i As Integer = Integer.Parse(s, Globalization.NumberStyles.Any) 2、型なしデータテーブルのフィールド値(Object型。DBのフィールドはNumberで数値またはNull)の場合はどのキャストを使うのでしょうか? (これは情報を失うことなく Int32 に変換できるとわかっている) Dim i As Integer = Convert.ToInt32(DirectCast(DataTable1.Rows(0).Item(0), Double)) | ||||||||||||||||||||||||
|
投稿日時: 2009-01-14 10:58
普段プログラミングをする上ではあまり厳密に考えなくてもよいかなと思っているのですが、 こうやって会話をする上では言葉の定義が人によって違うとすれ違いが発生するので、 このスレッドの中だけでも共通認識を持って話ができればいいなと思って例示しました。 #一般的なキャストの定義というのがわかりませんし、Wikipediaなどを見ても #型変換とキャストの用語の使い分けについては明確ではないようです。
ここでいう型変換とはどれを指していますか? 例示でなく私の意見として書いた 「キャスト=DirectCast/TryCast、型変換=その他」 という案で言うなら、キャストの方がパフォーマンスはよいです。
特殊仕様があることとパフォーマンスが悪いのと両方です。(主な理由は前者ですが) 例えば、渡されるデータが123か"123"か"123"のどれかの形式であることをプログラム上の 事前チェックなどで保証しているなら、CInt関数を使うのも動作上まずいということはありませんので、 わかって使う分には問題ありません。 そういう前提なしでユーザからの入力データにいきなりCInt関数を適用するような使用方法は、 先の一例で挙げたように"(123)"→-123に変換されるので、乱暴だということです。 (意図しないデータを入力できてしまう上に、ユーザが想定していない値とみなされる恐れがある)
CTypeを使った変換をキャストとみなすのか型変換とみなすのかは若干意見がわかれそうですが、 おおまかにはご提示の例の認識で私は問題ないと思います。
やり方はいろいろあると思いますが、1つの方法としてはありだと思います。
Nullではないことがはっきりしている場合は Dim i As Integer = Convert.ToInt32(DataTable1.Rows(0).Item(0)) で大丈夫だと思います。 Nullの場合は0として扱いたい場合は、DataTable1.Rows(0).Item(0)がDBNull.Valueか どうかのチェックが事前に必要になります。 (データベースから値を取得する場合、データの型が保証されているので、 CInt/CTypeでも実害はありませんので、そちらを使うのも一つの手です) ちなみに、CType(〜, Integer)はCIntと同じなので、Integer相手にCTypeを使ってよしとするなら、 CIntを嫌って無理にCTypeを使わなくてもCIntでよいと思います。 | ||||||||||||||||||||||||
|
投稿日時: 2009-01-14 12:43
なるほど、Convert.ToInt32 は Object を取るものがあるので、DirectCast も不要なんですね。私も勉強させていただきました。 http://msdn.microsoft.com/ja-jp/library/23511zys(VS.80).aspx 引数は IConvertible インターフェイスを実装する Object とありますから、内部的には IConvertible にキャストして、IConvertible.ToInt32 の Double での実装(Double.ToInt32)が使われるようですね。 |