c#:自定义隐式强制转换操作失败

本文关键字:转换 操作 失败 自定义 | 更新日期: 2023-09-27 18:06:58

好吧,我一直在试图找到有关这方面的任何信息。我构建了一个小类,以了解为字符串实现类型安全枚举有多困难,因为我希望将它们用于数据库字段名等。我一直不喜欢enum只能用于整型的事实。
然而,即使我已经为这个类实现了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帖子之一。

[MetaEDIT]忽略这个。我大错特错了。(/编辑)

c#:自定义隐式强制转换操作失败

用户定义的隐式和显式操作符完全是编译时机制,而不是运行时机制。一旦代码被编译,运行库就不知道任何用户定义的转换操作符。

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

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

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

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

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

在我看来,转换为SBool是一个更干净、更不容易出错的解决方案。

当您将Session[]强制转换为字符串时,您正在执行显式转换。没有定义SBool->String显式操作符,只有隐式操作符。

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