<< 【WPF】使い続け気付いたこと。Styleに使いどころ。 | main | 【C#】StackTraceとStackFrameで遊んでみた。 >>

【C#】OrderByより例外

JUGEMテーマ:コンピュータ
var list = new List<object> { 1L, 6L, 4, 2L };
var sortedList = list.OrderBy(item => item).ToList();

上記のコードが実行されると例外が発生します。OrderByによるソートが実行された際にlong型でない値と比較しようとするためですが・・・

List<object>型なんぞ使わずにList<long>型でコンパイル時に安全が確認出来るようにするべきというのが、コーディング的には正しい方法だと思いますが、今回は、上記の実行時の挙動をもう少し観察したいと思います。

まず、デバック実行でわかる情報(プログラマが知り得る情報)を見てみたいと思います。

OrderBy例外

例外はArgumentExceptionで「オブジェクトは Int64 型でなければなりません。」というメッセージが表示されています。long型以外の型のオブジェクトが引数に渡されたため例外が発生したという事ですね。List<ojbect>型に対してOrderByしているのでobject型の比較でソートがかかるものだとおもったのですが、これは意外です。

さて更に細かく見ていきたいと思います。

System.ArgumentException はハンドルされませんでした。
  Message="オブジェクトは Int64 型でなければなりません。"
  Source="mscorlib"
  StackTrace:
場所 System.Int64.CompareTo(Object value)
場所 System.Collections.Comparer.Compare(Object a, Object b)
場所 System.Collections.Generic.ObjectComparer`1.Compare(T x, T y)
場所 System.Linq.EnumerableSorter`2.CompareKeys(Int32 index1, Int32 index2)
場所 System.Linq.EnumerableSorter`1.QuickSort(Int32[] map, Int32 left, Int32 right)
場所 System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count)
場所 System.Linq.OrderedEnumerable`1.<GetEnumerator>d__0.MoveNext()
場所 System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
場所 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
場所 Art55.OrderBy20100306.Program.Main(String[] args) 場所 C:¥Users¥art55¥Documents¥Visual Studio 2008¥Projects¥Art55.OrderBy20100306¥Art55.OrderBy20100306¥Program.cs:行 13
場所 System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
場所 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
場所 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
場所 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
場所 System.Threading.ThreadHelper.ThreadStart()
  InnerException:

上記は例外発生時のスタックトレースです。

上から順に詳しく見ていくと

場所 System.Int64.CompareTo(Object value)

System.Int64構造体のCompareToメソッドが呼ばれていることがわかります。

恐らく6Lが格納されたSystem.Int64構造体のオブジェクトのCompareToメソッドに指定された引数がStystem.Int32構造体だったためArgumentExceptionが発生したものと推測されます。

場所 System.Collections.Comparer.Compare(Object a, Object b)
場所 System.Collections.Generic.ObjectComparer`1.Compare(T x, T y)

二つを同時に見てみます。ObjectComparer<T>のT型が一体何になっているのかきになるところですが、わかりません(恐らくobject型)。Compare(Object a, Object b)メソッドは公開されているメソッドなので、動作検証できます。

object o1 = 6L;
object o2 = 4;
Comparer.Default.Compare(o1, o2);

上記のコードでobject型同士の比較をしても、内部でlong型同士の比較が実行されるようで、同じようにArgumentExceptionが発生します。

MSDNライブラリーを覗いてみると
http://msdn.microsoft.com/ja-jp/library/system.collections.comparer.compare.aspx

例外
ArgumentException
条件
a と b が、いずれも IComparable インターフェイスを実装していません。
または
a と b の型が異なっていて、両者を比較できません。

解説

aIComparable を実装する場合は、a .CompareTo ( b ) が返されます。逆に、bIComparable を実装する場合は、符号反転した b .CompareTo ( a ) が返されます。

nullNothingnullptrnull 参照 (Visual Basic では Nothing) を任意の型と比較できます。このような比較を行っても、IComparable を使用した場合に例外が生成されることはありません。並べ替え処理では、nullNothingnullptrnull 参照 (Visual Basic では Nothing) は、他のすべてのオブジェクトより小さいと見なされます。

文字列比較の結果は、カルチャに応じて異なる場合があります。カルチャ固有の比較の詳細については、System.Globalization 名前空間のトピックおよび「エンコーディングとローカリゼーション」を参照してください。

渡された引数のうちIComparebleが実装されているオブジェクトを選んで、CompareToメソッドを呼び出すという事がわかりました。


ブログをかいてる途中で、もやもや感が解消したので、ここでいったん止めます(笑)


--------------
追記

object o = 4;
long d = (long) o;

上記のようなキャストは実行時にエラーになるので
下記のような修正はできません。

var list = new List<object> { 1L, 6L, 4, 2L };
var sortedList = list.OrderBy(item => (long) item).ToList();

List<object>のリストを作成した意図がなんなのか考慮した上で修正する必要があります。

※実行時にエラーはでなくなるけど、意図した動きとは違う動きをしてしまう例(↓)
var list = new List<object> { 1L, 6L, 4, 2L };
var sortedList = list.OfType<long>().OrderBy(item => item).ToList();



コメント
私は、例示されたコードがあると、OfType<T>して間違った方法をとってしまいそうです・・・。
var order = list.Select(i => Convert.ToInt64(i)).OrderBy(i => i).ToList();
あたりが無難なところですかね・・・
なぜint型とlong型が混在しているのかわからない状況なので、とりあえずソートとしたいという要求だけを満たすだけのコードであれば、

var order = list.OrderBy(i => Convert.ToInt64(i)).ToList();

これで元の型情報は失われることなく、ソートが可能です。あくまで前提条件付きのコードでし、その後のコードでもint型かlong型が気にする必要が出てくるので面倒なことになりそうです。

まあ、例外を発生されるために書いたコードなのであんまりつっこないでください。
  • art55
  • 2010/03/12 12:58 AM
あ〜そうか・・・。OrderByでlongに変換するだけでOKですね^^;
まだ、C#3.5で追加された新しい文法を使ったコードって完全に馴染みきれてないです。
  • かずき
  • 2010/03/14 9:14 AM
コメントする









この記事のトラックバックURL
トラックバック
calendar
   1234
567891011
12131415161718
19202122232425
2627282930  
<< September 2010 >>
あわせて読みたい
あわせて読みたいブログパーツ
selected entries
categories
archives
recent comment
recent trackback
recommend
キャット・シッターの君に。
キャット・シッターの君に。 (JUGEMレビュー »)
喜多嶋 隆
私のイラストレータデビュー本です。
recommend
ビジュアライジング・データ ―Processingによる情報視覚化手法
ビジュアライジング・データ ―Processingによる情報視覚化手法 (JUGEMレビュー »)
Ben Fry
javaぽい言語Processingを用いたビジュアライジングデータ。タイトルの通りいかにデータを視覚化するかというところを解説した本、手法やプロセスに対して丁寧でかつ具体的な例を挙げているのでわかりやすく、また応用が利きます。すばらしい本です。
recommend
recommend
recommend
recommend
recommend
recommend
Essential .NET ― 共通言語ランタイムの本質
Essential .NET ― 共通言語ランタイムの本質 (JUGEMレビュー »)
ドン・ボックス,クリス・セルズ,Don Box,Chris Sells,吉松 史彰
recommend
recommend
recommend
Design rule index―デザイン、新・100の法則
Design rule index―デザイン、新・100の法則 (JUGEMレビュー »)
William Lidwell,Kritina Holden,Jill Butler
ユーザインターフェイス、ユーザビリティなどを考えたいならこの本をヒントにしてみるのも良いかと思います。
recommend
リファクタリング―プログラムの体質改善テクニック (Object Technology Series)
リファクタリング―プログラムの体質改善テクニック (Object Technology Series) (JUGEMレビュー »)
マーチン ファウラー,Martin Fowler,児玉 公信,平澤 章,友野 晶夫,梅沢 真史
Javaで書かれていますが、良本です。言語を覚えたら、まずこの本を読んでみましょう。
recommend
集合知プログラミング
集合知プログラミング (JUGEMレビュー »)
Toby Segaran
・・・挫折中の一本。
recommend
C#ではじめるWebサービスプログラミング
C#ではじめるWebサービスプログラミング (JUGEMレビュー »)
山崎 秀,笠原 一浩
動くモノが作れるから楽しい、この本で実現しましょう!
recommend
C#クックブック 第3版
C#クックブック 第3版 (JUGEMレビュー »)
Jay Hilyard,Stephen Teilhet
C#2.0からの移行を考えているならこの本がお勧めです。
recommend
LINQテクノロジ入門~Microsoft Visual Studio 2008による新たなクエリ構築技法~ (マイクロソフトコンサルティングサービステクニカルリファレンスシリーズ) (マイクロソフトコンサルティングサービステクニカルリファレンスシリーズ)
LINQテクノロジ入門~Microsoft Visual Studio 2008による新たなクエリ構築技法~ (マイクロソフトコンサルティングサービステクニカルリファレンスシリーズ) (マイクロソフトコンサルティングサービステクニカルリファレンスシリーズ) (JUGEMレビュー »)
赤間信幸
LINQ最強の入門本です。LINQの処理をイメージをわかりやすく解説されています。また、著者の赤間さんはわかりやすい解説をされることで超有名です。
recommend
Pro LINQ: Language Integrated Query in C# 2008 (Windows.Net)
Pro LINQ: Language Integrated Query in C# 2008 (Windows.Net) (JUGEMレビュー »)
Jr. Rattz Joseph C.
LINQをしっかり学びたい方にお勧めします。
recommend
recommend
WPF Recipes in C# 2008: A Problem-Solution Approach (Expert's Voice in .Net)
WPF Recipes in C# 2008: A Problem-Solution Approach (Expert's Voice in .Net) (JUGEMレビュー »)
Sam Noble,Sam Bourton,Allen Jones
WPFの基礎を一通り学習したら、この本を手に取りましょう。WPFのHowToやDeepな情報を得ることが出来ます。かなりお勧めです。
(注意:サンプルコードのレイアウト設計は間違ってるので注意です)
links
profile
search this site.
others
mobile
qrcode
powered
無料ブログ作成サービス JUGEM
JUGEMのブログカスタマイズ講座