- PR -

キャストについて

投稿者投稿内容
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2009-01-09 17:38
引用:

テッテさんの書き込み (2009-01-09 15:51) より:
私は CInt は使いませんが、CType は使わざるを得ないこともあると思っています。

よねKENさんの挙げられた例1〜5では使う必要はないと思いますが、以下だとどうでしょう?

例6) Decimal型の変数に入っている値が、情報を失うことなく Int32 に変換できるとわかっている場合に、それを○○○してInt32型の変数に入れる。



この場合は、CInt/CType使っても、Math.〜使っても、Convert.ToInt32のどれ使っても同じ結果になりますね。
単なる好みの話になってしまいますが、私ならConvert.ToInt32(decimal)使いますかね。
(小数部0なので、特に意味はないですがCInt/CType、Convert.ToInt32(decimal)のどの場合も
銀行型丸めとして処理されます。)

※このパターンにCType使う場合、CType(変数, Int32)とすると思いますが、
 これはCIntの呼び出しとまったく同じです。

引用:

テッテさんの書き込み (2009-01-09 15:51) より:
例7) 型Aから型Bへの縮小変換が定義されていていて、型Aの変数に入っている型Aの値を○○○して型Bの変数に入れる。(演算子がオーバーロードされているという意味です。)

私はこういう場合、CType を使わざるを得ないと思っています。



CType演算子は知っているけど、使ったことがない状態で詳しくないですが、
CType 関数
で見ても、CType演算子とCType関数が関連しているようなので、
こちらはご指摘の通りのように思います。
#ここはちょっと自信なし。他の方法があったらご指摘お願いします。>ご覧の方。
テッテ
ベテラン
会議室デビュー日: 2008/03/16
投稿数: 91
投稿日時: 2009-01-09 22:25
引用:

よねKENさんの書き込み (2009-01-09 17:38) より:

この場合は、CInt/CType使っても、Math.〜使っても、Convert.ToInt32のどれ使っても同じ結果になりますね。
単なる好みの話になってしまいますが、私ならConvert.ToInt32(decimal)使いますかね。



なんというか…思い切り盲点を突かれた感じですw

そうですね…変換と考えれば Convert.ToInt32 でもいいし、Decimal.ToInt32 でもいいですね。

何と言うか、C# だと単純に (int) と書いちゃうところなので「キャスト」だと思いこんでて、VB でキャストっていうと DirectCast か CType しかないと思いこんでいました。

今後は ToInt32 を使うことにします。ありがとうございました。

引用:


CType演算子は知っているけど、使ったことがない状態で詳しくないですが、
CType 関数
で見ても、CType演算子とCType関数が関連しているようなので、
こちらはご指摘の通りのように思います。
#ここはちょっと自信なし。他の方法があったらご指摘お願いします。>ご覧の方。




私も自分でキャストを実装する機会はあまりないのですが、例えば System.Drawing の Point から Size には変換が実装されています。

Point.op_Explicit メソッド

こういう変換を行うときは、やはり CType しかないですよね。Point.op_Explicit ってそのまま書く手もありますが、それも気持ち悪いですし。
q
ベテラン
会議室デビュー日: 2009/01/06
投稿数: 54
投稿日時: 2009-01-10 10:34
(利用規約違反のため削除いたしました。@ITクラブメンバーシップセンター)
未記入
大ベテラン
会議室デビュー日: 2006/05/19
投稿数: 125
投稿日時: 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))
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2009-01-14 10:58
引用:

未記入さんの書き込み (2009-01-13 11:02) より:
キャストと変換について、今まで特に意識することなく使用していました。



普段プログラミングをする上ではあまり厳密に考えなくてもよいかなと思っているのですが、
こうやって会話をする上では言葉の定義が人によって違うとすれ違いが発生するので、
このスレッドの中だけでも共通認識を持って話ができればいいなと思って例示しました。
#一般的なキャストの定義というのがわかりませんし、Wikipediaなどを見ても
#型変換とキャストの用語の使い分けについては明確ではないようです。

引用:

未記入さんの書き込み (2009-01-13 11:02) より:
また型変換とキャストでは型変換の方がパフォーマンスがよいのでしょうか?



ここでいう型変換とはどれを指していますか?
例示でなく私の意見として書いた
「キャスト=DirectCast/TryCast、型変換=その他」
という案で言うなら、キャストの方がパフォーマンスはよいです。

引用:

そうではなくCtypeやCintは内部で何をしているか分からないから使用しない方がよいのでしょうか?



特殊仕様があることとパフォーマンスが悪いのと両方です。(主な理由は前者ですが)

例えば、渡されるデータが123か"123"か"123"のどれかの形式であることをプログラム上の
事前チェックなどで保証しているなら、CInt関数を使うのも動作上まずいということはありませんので、
わかって使う分には問題ありません。
そういう前提なしでユーザからの入力データにいきなりCInt関数を適用するような使用方法は、
先の一例で挙げたように"(123)"→-123に変換されるので、乱暴だということです。
(意図しないデータを入力できてしまう上に、ユーザが想定していない値とみなされる恐れがある)

引用:

以下のようにまとめましたが、合っていますでしょうか?



CTypeを使った変換をキャストとみなすのか型変換とみなすのかは若干意見がわかれそうですが、
おおまかにはご提示の例の認識で私は問題ないと思います。

引用:

私が最初に質問した回答は以下のようになりましたが、合っていますでしょうか?
1、テキストボックスに入力されている数字(カンマ区切りの数字文字列または全角数字を含む)を数値にキャストする場合はどのキャストを使うのでしょうか?
一旦半角に変換し、Parseを使用する。
Dim s As String = Strings.StrConv(Me.TextBox1.Text, VbStrConv.Narrow)
Dim i As Integer = Integer.Parse(s, Globalization.NumberStyles.Any)



やり方はいろいろあると思いますが、1つの方法としてはありだと思います。

引用:

2、型なしデータテーブルのフィールド値(Object型。DBのフィールドはNumberで数値またはNull)の場合はどのキャストを使うのでしょうか?
(これは情報を失うことなく Int32 に変換できるとわかっている)
Dim i As Integer = Convert.ToInt32(DirectCast(DataTable1.Rows(0).Item(0), Double))



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でよいと思います。
テッテ
ベテラン
会議室デビュー日: 2008/03/16
投稿数: 91
投稿日時: 2009-01-14 12:43
引用:

よねKENさんの書き込み (2009-01-14 10:58) より:
Nullではないことがはっきりしている場合は
Dim i As Integer = Convert.ToInt32(DataTable1.Rows(0).Item(0))
で大丈夫だと思います。


なるほど、Convert.ToInt32 は Object を取るものがあるので、DirectCast も不要なんですね。私も勉強させていただきました。

http://msdn.microsoft.com/ja-jp/library/23511zys(VS.80).aspx

引数は IConvertible インターフェイスを実装する Object とありますから、内部的には IConvertible にキャストして、IConvertible.ToInt32 の Double での実装(Double.ToInt32)が使われるようですね。

スキルアップ/キャリアアップ(JOB@IT)