kazuakix の日記

Windows Phone とか好きです

要素がコレクションの何番目にあるかを調べたい

という訳で、ようやくユニバーサル アプリに着手します。*1

基本的には WP のアレや Win8 のアレからコードを引っ張ってくるつもりですが、せっかくなので やっつけだった部分を直しながら行こうと思います。近々 dat の取得方法も変わるらしいので全面的に見直すいい機会ですね。
 

そんな訳で 前のコードで一番いけてなかった URL の処理を直していました。
基本的には System.Uri をベースにして "/test/read.cgi/" が含まれていればその前後から情報を取ろうという考えです。

public class BbsUri : Uri
{
    public BbsUri(string uri) : base (uri) { }
}

 
System.Uri には Segments という便利なプロパティがあるので、FindIndex メソッドで "read.cgi/" の場所を と思ったのですが...

    public BbsUri(string uri) : base (uri)
    {
        var idx = this.Segments
            .FindIndex(_ => _.Equals("read.cgi/")); // ダメ

Uri.Segments は List ではなく string[] なので FindIndex メソッドが使えないんですね。
 
普通に前から調べていけばいいのですが、なんとか一発で書く方法はないかなぁ...と調べているとこんな情報を発見。

これはよさそうですね。

早速試してみました。

    public BbsUri(string uri) : base (uri)
    {
        var readcgi = this.Segments
            .Select((v, i) => new { Value = v, Index = i })
            .Where(_ => _.Value.Equals("read.cgi/")).FirstOrDefault();
        if (readcgi != null && 0 <= readcgi.Index)
        {
            // いろいろ

これはこれで動いたんですが、ちょっと長いですね...。あと目的の文字列が含まれていない時に Null チェックしないといけないのも余計です。
 
で、今日のオチは string[] (Array) には IndexOfメソッドがあるので、それ使えって事でした*2。ワオ!短くなったネ!

    public BbsUri(string uri) : base (uri)
    {
        int idx = Array.IndexOf(this.Segments, "read.cgi/");
        if (0 <= idx)
        {
            // いろいろ


補足

2 つ目のパターンについて、ネタ元のかずきさんから Where → FirstOrDefault は 1 つにまとめられるよと教えて頂きました。


こんな感じでしょうか。すっきりしていい感じですね。

    public BbsUri(string uri) : base (uri)
    {
        var readcgi = this.Segments
            .Select((v, i) => new { Value = v, Index = i })
            .FirstOrDefault(s => s.Value.Equals("read.cgi/"));
        if (readcgi != null && 0 <= readcgi.Index)
        {
            // いろいろ

*1:宣言により自分を追い込むスタイル

*2:static メソッドなんで気づきませんでした...