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

C#:自定义隐式强制转换运算符失败,c#,casting,asp.net-4.0,implicit,C#,Casting,Asp.net 4.0,Implicit,好吧,我已经试着找到这方面的信息有一段时间了。我构建了一个小类,以了解为字符串实现类型安全枚举有多困难,因为我想将它们用于数据库字段名等。我从不喜欢枚举只能用于整数的事实。 然而,尽管我已经为这个类实现了一个隐式操作符,但每次我尝试使用它时,它都会给我一个无效的强制转换异常。我不知所措,因为此时我看不出我的代码有什么问题。 这是课程: /// <summary> /// SBool - type-safe-enum for boolean strings /// </summa

好吧,我已经试着找到这方面的信息有一段时间了。我构建了一个小类,以了解为字符串实现类型安全枚举有多困难,因为我想将它们用于数据库字段名等。我从不喜欢枚举只能用于整数的事实。
然而,尽管我已经为这个类实现了一个
隐式操作符
,但每次我尝试使用它时,它都会给我一个无效的强制转换异常。我不知所措,因为此时我看不出我的代码有什么问题。
这是课程:

/// <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;
    }
}
//
///SBool-布尔字符串的类型安全枚举
/// 
公共密封类SBool
{
私有只读字符串名称;
私有只读int值;
//这些人是为了转换他们在另一种情况下可能会更好,
//但对于这一次,他们并不是很有帮助。
//((即,它们也不起作用。)
//私有静态只读字典stringsByBool=newdictionary();
//私有静态只读字典boolsByString=new Dictionary();
public static readonly SBool True=新的SBool(1,“True”);
公共静态只读SBool False=新SBool(0,“False”);
私有SBool(int值、字符串名称)
{
this.name=名称;
这个值=值;
//stringsByBool[this]=名称;
//boolsByString[name]=这个;
}
私人SBool(SBool SBool)
{
this.name=sbool.name;
this.value=sbool.value;
//stringsByBool[this]=名称;
//boolsByString[name]=这个;
}
公共重写字符串ToString()
{
返回名称;
}
/// 
///允许将SBools隐式转换为字符串
/// 
///要铸成字符串的工具
///SBool的等效字符串(其值)
公共静态隐式运算符字符串(SBool SBool)
{
if(sbool==sbool.True)
返回SBool.True.name;
其他的
返回SBool.False.name;
}
/// 
///将字符串隐式转换为SBool。
/// 
///尝试强制转换为SBool的字符串
///字符串的SBool等效项,
///SBool.False,如果不是“true”或“False”。
公共静态显式运算符SBool(字符串str)
{
如果(!String.IsNullOrEmpty(str)&&str.ToLower()=“true”)
返回SBool.True;
其他的
返回SBool.False;
}
公共静态布尔运算符==(SBool左、SBool右)
{
返回left.value==right.value;
}
公共静态布尔运算符!=(SBool左,SBool右)
{
返回left.value!=right.value;
}
}

这在检查会话变量时失败:
如果(((字符串)会话[“变量])==SBool.False)
带有InvalidCastException,
坦率地说,我不知道为什么

提前感谢;任何人都可以解释为什么这不起作用(并非所有领域都提供cookies)。我会把其他事情修好,但如果有什么不清楚的地方,请告诉我。有关类型安全枚举的更多信息,下面是我基于的类


[MetaEDIT]忽略此项。我大错特错了。[/edit]

如果将会话[]强制转换为字符串,则执行显式转换。您没有定义SBool->String显式运算符,只有隐式运算符


您需要添加显式SBool->string转换。

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

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

在这种情况下,您不是从
SBool
转换为
字符串
,而是从
对象
转换为
字符串
(就编译器而言),并且没有转换操作符来处理该问题

您需要首先将
会话
变量的结果强制转换为
SBool
(实际上就是这样),然后转换为其他类型,以便能够利用用户定义的转换运算符。因此:

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

将很好地工作。

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


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

您是否尝试过将
Session[“variable”]
强制转换为
SBool而不是字符串?或者是一个
字符串
,然后是一个
SBool
SBool.False
是一个布尔正确的。。。?如果您正在检查它是否相等,为什么不将
==
右侧的值强制转换为
如果((字符串)会话[“变量”])==SBool.False.ToString()
强制转换错误是正确的,顺便说一句
最有可能的例外是关于这个强制转换
(字符串)会话[“变量”]
@Lanorkin:如果我没弄错
(string)
不应抛出异常;如果
会话[“var”]
无效,它将简单地返回“-@DJKRAZE:关键是不必每次都抛出字符串。这就是为什么我首先使用隐式强制转换。@firesburnsup
会话
可能包含绝对任何类型的对象,因此您可以轻松获得invalidca