C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: CTypeの第2引数 "Object (As Type)"


(過去ログ 15 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■5548 / inTopicNo.1)  CTypeの第2引数 "Object (As Type)"
  
□投稿者/ まんぼう (3回)-(2007/07/18(Wed) 08:39:32)

分類:[.NET 全般] 

2007/07/18(Wed) 08:55:30 編集(投稿者)
CTypeの第2引数 "Object (As Type)" の指定方法について教えてください。
環境は、VB2005, WinFormです。

DataRowを処理するプログラムにおいて、とある事情でRowStateを使わずに項目を1つずつOriginalと比較して変更有無を検出しています。
以下がそのコードです。

Dim isChanged As Boolean = False
Dim row As DataSet1.Table1Row
For Each column As DataColumn In DataSet1.Table1.Columns
    If row(column.ToString, DataRowVersion.Current) <> row(column.ToString, DataRowVersion.Original) Then '※
        isChanged = True
        Exit For
    End If
Next

※行で、row(idx)はObjectを返すので
「Option Strict On では、演算子 '<>' に対して Object 型のオペランドを使うことはできません。オブジェクト ID をテストするには、'Is' 演算子を使用してください。」
というコンパイルエラーになります。

しかしIsやIsNotを使って比較すると、両辺のrow(idx)の値(例えばString)が同一であるにも関わらずオブジェクト同士はIsNotだ、と返ってくる場合があります。
これは、CTypeで両辺をColumnの型(Stringなど)に変換した上で<>演算子で比較する必要があるのかと思いました。

そこでそのCTypeの書き方なのですが、

CType(row(column.ToString, DataRowVersion.Current), XXX)

このXXXに何を書けばよいのでしょうか?Columnの型はString以外もあるので、決め打ちができません。
column.GetTypeとしても「型 column.gettypeが定義されていません」というエラーになりました…

#訂正
※行で、row(idx)はObjectを返すので
※行で、row(columnName As String, version As System.Data.DataRowVersion)はObjectを返すので

引用返信 編集キー/
■5550 / inTopicNo.2)  Re[1]: CTypeの第2引数 "Object (As Type)"
□投稿者/ まどか (332回)-(2007/07/18(Wed) 09:25:45)
> ※行で、row(idx)はObjectを返すので
> 「Option Strict On では、演算子 '<>' に対して Object 型のオペランドを使うことはできません。オブジェクト ID をテストするには、'Is' 演算子を使用してください。」
> というコンパイルエラーになります。
>
> しかしIsやIsNotを使って比較すると、両辺のrow(idx)の値(例えばString)が同一であるにも関わらずオブジェクト同士はIsNotだ、と返ってくる場合があります。
> これは、CTypeで両辺をColumnの型(Stringなど)に変換した上で<>演算子で比較する必要があるのかと思いました。

「場合がある」とか「必要がある」ではありません。
「適切な演算子を使用する」になります。

値型と参照型
http://msdn2.microsoft.com/ja-jp/library/t63sy5hs(VS.80).aspx

> CType(row(column.ToString, DataRowVersion.Current), XXX)
>
> このXXXに何を書けばよいのでしょうか?Columnの型はString以外もあるので、決め打ちができません。

ToStringメソッドは「表示用文字列の取得」ですので用途として不適切です。
そのクラスのToStringメソッドの実装(返値)を知っている、何が返ってきてもOK、という場合に使用するようにしてください。
したがって引数の意味どおり「列名を表す」ものを指定する必要があります。
それとXXXを知る方法とあわせてDataColumnクラスのメンバを調べてみてください。

引用返信 編集キー/
■5551 / inTopicNo.3)  Re[1]: CTypeの第2引数 "Object (As Type)"
□投稿者/ よねKEN (55回)-(2007/07/18(Wed) 09:25:50)
よねKEN さんの Web サイト
No5548 (まんぼう さん) に返信
> If row(column.ToString, DataRowVersion.Current) <> row(column.ToString, DataRowVersion.Original) Then '※

If Not row(column.ToString, DataRowVersion.Current).Equals(row(column.ToString, DataRowVersion.Original)) Then

のようにEqualsメソッドで等値比較を行えばよいかと思います。

> CType(row(column.ToString, DataRowVersion.Current), XXX)
>
> このXXXに何を書けばよいのでしょうか?Columnの型はString以外もあるので、決め打ちができません。
> column.GetTypeとしても「型 column.gettypeが定義されていません」というエラーになりました…

DataColumnのDataTypeプロパティで型は判断できないでしょうか?
#動作未検証。

引用返信 編集キー/
■5553 / inTopicNo.4)  Re[2]: CTypeの第2引数 "Object (As Type)"
□投稿者/ まんぼう (4回)-(2007/07/18(Wed) 10:14:38)
> したがって引数の意味どおり「列名を表す」ものを指定する必要があります。
column.ColumnNameにすべきでした;;

> それとXXXを知る方法とあわせてDataColumnクラスのメンバを調べてみてください。
XXXはまだ分からないのですが、DataColumnクラスのメンバを調べてみてください、というのは(下でかぶった?よねKEN さんご指摘の)Equalsの事を意図していらっしゃったのでしょうか?(だとしたら私はラッキー?アンラッキー?^^;)
引用返信 編集キー/
■5554 / inTopicNo.5)  Re[2]: CTypeの第2引数 "Object (As Type)"
□投稿者/ まんぼう (5回)-(2007/07/18(Wed) 10:19:02)
2007/07/18(Wed) 10:27:00 編集(投稿者)
2007/07/18(Wed) 10:26:48 編集(投稿者)

> If Not row(column.ToString, DataRowVersion.Current).Equals(row(column.ToString, DataRowVersion.Original)) Then
>
> のようにEqualsメソッドで等値比較を行えばよいかと思います。

Equalsでできました。
ちなみに勉強のためMSDNでObject.Equalsを調べたことを整理すると、(即席です)

・Isは参照が同じかどうかを比較する。
・Equalsも規定では参照が同じか比較するが、オーバーライドすることで値が同じかどうかを比較することができる。
・DataColumn.Equalsはオーバーライドされており、値の比較を行う。
・従って、column(As DataColumn)変数のメソッドEqualsを使えばColumnがどんな型であっても値の比較を行ってくれる。
・このケースではCTypeよりもEqualsの方が用途にぴったり当てはまる。

ということが分かりました。

(だから、Ctypeの第2引数には決め打ち方法しか用意されていない?)

> DataColumnのDataTypeプロパティで型は判断できないでしょうか?
> #動作未検証。
やってみると、同様のコンパイルエラーが出ました。(型が定義されていません)
CTypeの方法をもう少し調べてみます。

ともあれ、まどかさん、よねKENさんありがとうございます。

#訂正
オーバーライド→オーバーロード(;_;

引用返信 編集キー/
■5563 / inTopicNo.6)  Re[3]: CTypeの第2引数 "Object (As Type)"
□投稿者/ よねKEN (56回)-(2007/07/18(Wed) 13:21:45)
よねKEN さんの Web サイト
2007/07/18(Wed) 14:25:25 編集(投稿者)

No5554 (まんぼう さん) に返信
>>If Not row(column.ToString, DataRowVersion.Current).Equals(row(column.ToString, DataRowVersion.Original)) Then
>>
>>のようにEqualsメソッドで等値比較を行えばよいかと思います。
>
> Equalsでできました。

私の示したEqualsメソッドを使う案ですが、これは
DataRowクラスのItemプロパティ(引数はDataColumn, DataRowVersion) が返すオブジェクトに
対してEqualsメソッドを呼び出しています。

つまり、あるカラムがStringを返すものなら、StringのEqualsが、Int32を返すものならInt32のEqualsが
といった形でそれぞれのインスタンスのEqualsメソッドを呼び出されます。

> ・DataColumn.Equalsはオーバーライドされており、値の比較を行う。
> ・従って、column(As DataColumn)変数のメソッドEqualsを使えばColumnがどんな型であっても値の比較を行ってくれる。

これは私の示したコードを勘違いされているように思います。

> (だから、Ctypeの第2引数には決め打ち方法しか用意されていない?)
>
>>DataColumnのDataTypeプロパティで型は判断できないでしょうか?
>>#動作未検証。
> やってみると、同様のコンパイルエラーが出ました。(型が定義されていません)
> CTypeの方法をもう少し調べてみます。

型はたぶん判定できますが、よく考えるとCTypeによる変換はあまり意味がないですね。
DataColumn.DataTypeで何型かわかっても、キャストした後に、
例えば、それがString型ならSting型の変数に入れてあげる必要がありますので。

引用返信 編集キー/
■5590 / inTopicNo.7)  Re[4]: CTypeの第2引数 "Object (As Type)"
□投稿者/ まんぼう (6回)-(2007/07/18(Wed) 19:55:00)
No5563 (よねKEN さん) に返信
> 私の示したEqualsメソッドを使う案ですが、これは
> DataRowクラスのItemプロパティ(引数はDataColumn, DataRowVersion) が返すオブジェクトに
> 対してEqualsメソッドを呼び出しています。
>
> つまり、あるカラムがStringを返すものなら、StringのEqualsが、Int32を返すものならInt32のEqualsが
> といった形でそれぞれのインスタンスのEqualsメソッドを呼び出されます。

全然勘違いしてました…。
そして分かりやすいご説明ありがとうございます。とても勉強になります。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -