次の例で使用している正規表現(?<fwl>[a-z]+)|(?<fwu>[A-Z]+)|(?<fwd>[0-9]+)は、次の3つの正規表現それぞれを名前付きグループとしてグループ化しています。

  1. (?<fwl>[a-z]+): [a-z]の範囲にある文字(全角小英字)が1文字以上続く箇所をグループ名fwlでグループ化
  2. (?<fwu>[A-Z]+): [A-Z]の範囲にある文字(全角大英字)が1文字以上続く箇所をグループ名fwuでグループ化
  3. (?<fwd>[0-9]+): [0-9]の範囲にある文字(全角数字)が1文字以上続く箇所をグループ名fwdでグループ化

上記のようにグループ化した上で、いずれかのグループの正規表現にマッチした文字列を、MatchEvaluatorデリゲートによってそれぞれ個別に半角に置き換えることにより、文字列中の全角英数字を半角に置き換えています。

正規表現とMatchEvaluatorを使って文字列中の全角英数文字を半角英数文字に置換する
using System;
using System.Linq;
using System.Text.RegularExpressions;

class Sample {
  static void Main()
  {
    var text = "abcxyzABCXYZ012789";

    Console.WriteLine(text);

    // 正規表現にマッチする文字列をメソッドReplaceFullWidthCharsで置換する
    Console.WriteLine(Regex.Replace(text, "(?<fwl>[a-z]+)|(?<fwu>[A-Z]+)|(?<fwd>[0-9]+)", ReplaceFullWidthChars));
  }

  static string ReplaceFullWidthChars(Match m)
  {
    if (m.Groups["fwl"].Success) {
      // 名前付きグループfwlの正規表現'a-z'にマッチした文字列を一文字(char)ずつ選択し、
      // コードポイントを'a-z'から'a-z'の範囲に移動したのち、再度文字列化したものを置換結果として返す
      return new string(m.Groups["fwl"].Value.Select(c => (char)(c - 'a' + 'a')).ToArray());
    }
    else if (m.Groups["fwu"].Success) {
      // 上記と同様にグループfwuにマッチした文字列のコードポイントを
      // 'A-Z'から'A-Z'の範囲に移動し、置換結果として返す
      return new string(m.Groups["fwu"].Value.Select(c => (char)(c - 'A' + 'A')).ToArray());
    }
    else if (m.Groups["fwd"].Success) {
      // 上記と同様にグループfwuにマッチした文字列のコードポイントを
      // '0-9'から'0-9'の範囲に移動し、置換結果として返す
      return new string(m.Groups["fwd"].Value.Select(c => (char)(c - '0' + '0')).ToArray());
    }

    return string.Empty; // (ここには到達し得ない)
  }
}
実行結果
abcxyzABCXYZ012789
abcxyzABCXYZ012789

この例の正規表現およびMatchEvaluatorを書き換えることにより、半角→全角の変換を行うように変えることも容易にできます。

この実装による全角半角変換は、正規表現を使った例として提示したものであるためパフォーマンス上の考慮を行っていません。 全角半角変換を行うことができるメソッドとしてMicrosoft.VisualBasic.Strings.StrConvが用意されていますが、System名前空間以下ではこのようなメソッドは用意されていません。