11

さて、私はしばらくの間、これに関する情報を見つけようとしてきました。データベースのフィールド名などに使用したいので、文字列に対してタイプセーフな列挙型を実装するのがいかに難しいかを確認するために、小さなクラスを作成しました。列挙型が整数にのみ使用できるという事実が好きではありませんでした。
ただし、このクラスに を実装したにもかかわらず、implicit operator使用しようとするたびに無効なキャスト例外が発生します。この時点でコードに問題は見られないので、途方に暮れています。
クラスは次のとおりです。

/// <summary>
/// SBool - type-safe-enum for boolean strings
/// </summary>
public sealed class SBool
{

    private readonly String name;
    private readonly int value;

    // these guys were for conversions. They might work better in another case,
    //  but for this one, they weren't very helpful.
    // ((I.e. they didn't work either.))
    //private static readonly Dictionary<SBool, String> stringsByBool = new Dictionary<SBool, String>();
    //private static readonly Dictionary<String, SBool> boolsByString = new Dictionary<String, SBool>();

    public static readonly SBool True = new SBool( 1, "true" );
    public static readonly SBool False = new SBool( 0, "false" );

    private SBool( int value, String name )
    {
        this.name = name;
        this.value = value;
        //stringsByBool[this] = name;
        //boolsByString[name] = this;
    }

    private SBool( SBool sbool )
    {
        this.name = sbool.name;
        this.value = sbool.value;
        //stringsByBool[this] = name;
        //boolsByString[name] = this;
    }

    public override String ToString()
    {
        return name;
    }

    /// <summary>
    /// allows implicit casting of SBools to strings
    /// </summary>
    /// <param name="sbool">the SBool to cast into a string</param>
    /// <returns>the string equivalent of the SBool (its value)</returns>
    public static implicit operator String( SBool sbool )
    {
        if ( sbool == SBool.True )
            return SBool.True.name;
        else
            return SBool.False.name;
    }

    /// <summary>
    /// implicitly cast a string into a SBool.
    /// </summary>
    /// <param name="str">the string to attempt to cast as a SBool</param>
    /// <returns>the SBool equivalent of the string,
    /// SBool.False if not either "true" or "false".</returns>
    public static explicit operator SBool( String str )
    {
        if ( !String.IsNullOrEmpty(str) && str.ToLower() == "true" )
            return SBool.True;
        else
            return SBool.False;
    }

    public static bool operator ==( SBool left, SBool right )
    {
        return left.value == right.value;
    }

    public static bool operator !=( SBool left, SBool right )
    {
        return left.value != right.value;
    }
}


これはセッション変数のチェックで失敗しています:
if( ( (string)Session["variable"] ) == SBool.False )InvalidCastException で、
率直に言って理由がわかりません。

前もって感謝します; これが機能しない理由を説明できる人のための Cookie (Cookie はすべての地域で利用できるわけではありません)。他にも修正していきますが、不明な点がありましたらお知らせください。タイプ セーフな列挙型の詳細については、このクラスの基になった SO 投稿の 1 つを参照してください。

[MetaEDIT] これは無視してください。私は恐ろしく、恐ろしく間違っていました。[/編集]

4

3 に答える 3

12

ユーザー定義の暗黙的および明示的な演算子は、ランタイム メカニズムではなく、完全にコンパイル時のメカニズムです。コードがコンパイルされると、ランタイムはユーザー定義の変換演算子を認識しません。

コンパイラが型チェックを行っているときに、 aFooが期待されているが実際の値が aであるBarことを確認すると、最初に組み込み言語の暗黙的な変換演算子をチェックして、適切な変換が存在するかどうかを確認します。そうでない場合は、両方の定義をチェックし、Foo暗黙Bar的な変換演算子を見つけた場合は、関連する静的メソッドへの呼び出しに追加して変換を実行します。ランタイムに到達すると、組み込みの言語の暗黙的な演算子のみが適用されます。

この場合、 から への変換ではなくSBool、(コンパイラに関する限り) から への変換であり、それを処理する変換演算子はありませstringobjectstring

Sessionユーザー定義の変換演算子を利用できるようにするには、最初に変数の結果をSBool(これが実際のものです) にキャストし、次に他の型にキャストする必要があります。そう:

if( ( (SBool)Session["variable"] ) == SBool.False )

うまくいきます。

于 2013-04-02T15:11:18.643 に答える