web-dev-qa-db-ja.com

IEnumerableとして文字列を使用する

.NET for Windowsストアアプリでは、文字列を列挙型として使用できなくなったようです。次のコードはデスクトップアプリケーションでは機能しますが、アプリでは機能しません。

_public static bool SolelyConsistsOfLetters(string s)
{
    return s.All(c => char.IsLetter(c));
}
_

エラーは

「string」には「All」の定義が含まれておらず、「string」タイプの最初の引数を受け入れる拡張メソッド「All」が見つかりませんでした(usingディレクティブまたはアセンブリ参照がありませんか?)

しかし、私はアセンブリ参照または_using System.Linq;_を見逃していません。次のコードdoes動作します:

_public static IEnumerable<char> StringAsEnumerable(string s)
{
    foreach (char c in s)
    {
        yield return c;
    }
}

public static bool SolelyConsistsOfLetters(string s)
{
    return StringAsEnumerable(s).All(c => char.IsLetter(c));
}
_

問題は、_s as IEnumerable<char>_が機能せず(エラー:「タイプ 'string'を 'System.Collections.Generic.IEnumerable'(..)に変換できません」)、s.GetEnumerator()が使用できないことです。

私の質問:

  1. 文字列をEnumerablesとして使用するエレガントな方法は本当にありませんか(上記のようなヘルパーメソッドなしで)?当たり前のことを見逃しているに違いない気がします。
  2. 文字列はEnumerableのように動作しないので、foreachがここで機能する理由/方法は何ですか?
20

String.IEnumerable<Char>.GetEnumerator メソッドは.NET for Windowsストアアプリケーションではサポートされていませんが、非ジェネリック String.IEnumerable.GetEnumerator がサポートされているため、foreachアプローチが機能します。

これに基づいて、次のことも可能であると私は信じています。

s.Cast<char>().All(c => char.IsLetter(c))

[〜#〜] update [〜#〜](Janiコメントに関して)foreachは、それぞれを定義することにより、すでにキャストを実行しています。 charとしての変数。非汎用のIEnumerableバージョンはオブジェクトを返し、コンパイル時にオブジェクトから他のタイプへのすべてのキャストが受け入れられるため、それが機能します。

次のコードも正常にコンパイルされますが、実行時に失敗します。

var valid = new object[] {'1', '2', '3'};

foreach (char c in valid)
    Console.WriteLine(c);

var invalid = new object[] { 1, 2, 3 };

foreach (char c in invalid)
    Console.WriteLine(c); // Fails at runtime; InvalidCastException
18
João Angelo