繁体   English   中英

C#:自定义隐式转换运算符失败

[英]C# : Custom implicit cast operator failing

好吧,我一直试图找到有关这方面的任何信息。 我构建了一个小类来查看为字符串实现类型安全枚举的难度,因为我想将它们用于数据库字段名等。 我从来不喜欢枚举只能用于整数的事实。
但是,即使我已经为这个类实现了一个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;
    }
}


这在检查Session变量时失败了:
if( ( (string)Session["variable"] ) == SBool.False )带有InvalidCastException,
我坦率地不明白为什么。

提前致谢; 任何人都可以解释为什么这不起作用的cookie(饼干不是在所有领域都可用)。 我将修复其他问题,但如果有任何不清楚的地方,请告诉我。 有关Type-Safe枚举的更多信息,这是我基于此课程的SO帖子之一。

[MetaEDIT]无视这一点。 我非常可怕,非常错误。 [/编辑]

用户定义的隐式和显式运算符完全是编译时机制,而不是运行时机制。 编译代码后,运行时不知道任何用户定义的转换运算符。

当编译器进行类型检查并看到Foo是预期的但实际值是Bar ,它将首先检查内置语言隐式转换运算符,以查看是否存在适当的转换。 如果没有,它会检查隐式转换运算符的FooBar的定义,如果它找到一个它将添加到相关静态方法的调用中以执行转换。 一旦进入运行时,将仅应用内置语言隐式运算符。

在这种情况下,您不是从SBool转换为string ,而是从object转换为string (就编译器而言)并且没有转换运算符来处理它。

您需要首先将Session变量的结果转换为SBool (实际上是它),然后转换为其他类型,以便能够利用用户定义的转换运算符。 所以:

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

会工作得很好。

正如Servy所说,这些类型的演员阵容发生在编译时。 但是,有一种方法可以通过使用动态关键字在运行时强制执行此检查。 而不是将SBool强制转换为动态。 这将导致在运行时执行强制转换操作符。

在我看来,转向SBool是一种更清晰且不易出错的解决方案。

你正在将Session []转换为字符串,你正在进行显式转换。 您没有定义SBool-> String显式运算符,只是隐式运算符。

您需要添加显式的SBool->字符串转换。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM