Home / ぼやきごと / 2013-03-15
2013-03-15

C#:サロゲートペアを考慮した文字の列挙に拡張メソッドも使えるようにする

Prev: [C#:サロゲートペアを考慮した文字の列挙に foreach を使えるようにする]

昨日の記事の続き…というか改良版。

前回作った TextElementEnumerable クラスは IEnumerable インタフェースを実装していましたが、 System.Linq.Enumerable 静的クラスにある豊富な拡張メソッドを利用するためには IEnumerable<T> ジェネリックインタフェースをこそ実装すべきです。
そして IEnumerable<T>.GetEnumerator メソッドの実装には yield return 文を使うのが簡単です。

というわけで、改良した TextElementEnumerable クラスはこちら。

すべて開くすべて閉じる
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 
 
 
 
 
 
-
-
|
|
!
-
-
|
|
|
!
-
|
!
|
-
|
|
!
|
-
|
|
|
!
-
|
|
-
|
!
!
|
|
|
|
-
|
!
|
|
!
!
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
 
namespace ruche.util
{
    /// <summary>
    /// 文字列に対するUnicode文字の列挙子を公開するクラス。
    /// </summary>
    public class TextElementEnumerable : IEnumerable<string>
    {
        /// <summary>
        /// コンストラクタ。
        /// </summary>
        /// <param name="source">列挙対象となる文字列。</param>
        public TextElementEnumerable(string source)
        {
            this.Source = source;
        }
 
        /// <summary>
        /// 列挙対象文字列を取得する。
        /// </summary>
        public string Source { get; private set; }
 
        /// <summary>
        /// Unicode文字の列挙子を取得する。
        /// </summary>
        /// <returns>Unicode文字の列挙子。</returns>
        public IEnumerator<string> GetEnumerator()
        {
            var e = StringInfo.GetTextElementEnumerator(this.Source);
            while (e.MoveNext())
            {
                yield return e.GetTextElement();
            }
        }
 
        #region IEnumerable の明示的実装
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
 
        #endregion
    }
}

これで System.Linq.Enumerable 静的クラスの拡張メソッドも利用可能になります。

すべて開くすべて閉じる
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 
 
-
!
 
-
!
-
-
!
string text = "あいうえお";
 
// 拡張メソッドが使える(using System.Linq が必要)
int unicodeLen = (new TextElementEnumerable(text)).Count();
 
// foreach でも型推論が使える
foreach (var s in new TextElementEnumerable(text))
{
    // 内容略
}

ちなみに、利用する場所が限られているのならば、わざわざ TextElementEnumerable クラスを作らずとも下記のようなメソッドを作るだけでも事足ります。

すべて開くすべて閉じる
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
-
|
|
|
|
!
-
|
|
-
|
!
!
/// <summary>
/// 文字列に対するUnicode文字の列挙子を公開するオブジェクトを取得する。
/// </summary>
/// <param name="source">列挙対象となる文字列。</param>
/// <returns>Unicode文字の列挙子を公開するオブジェクト。</returns>
private IEnumerable<string> GetTextElementEnumerable(string source)
{
    var e = StringInfo.GetTextElementEnumerator(source);
    while (e.MoveNext())
    {
        yield return e.GetTextElement();
    }
}

これで new TextElementEnumerable(xxx) の代わりに GetTextElementEnumerable(xxx) と書くことができます。

Category: [プログラミング][C#] - 2013-03-15 00:05:35