【问题标题】:C# : Custom implicit cast operator failingC#:自定义隐式转换运算符失败
【发布时间】:2013-04-02 14:54:02
【问题描述】:

好的,我一直在努力寻找有关这方面的任何信息。我构建了一个小类来查看类型安全枚举对于字符串的实现有多难,因为我想将它们用于数据库字段名称等。我从不喜欢枚举只能用于整数的事实。
然而,即使我已经为这个类实现了一个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 并非在所有地区都可用)。我将解决其他问题,但如果有任何不清楚的地方,请告诉我。有关类型安全枚举的更多信息,这里是 one of the SO posts 我基于此类。

[MetaEDIT] 忽略这一点。我大错特错,大错特错。 [/编辑]

【问题讨论】:

  • 您是否尝试将Session["variable"] 转换为SBool 而不是字符串?或者到string,然后是SBool
  • sBool.False 是正确的布尔值...?如果您正在检查它是否相等,为什么不在== 右侧将该值转换为if( ( (string)Session["variable"] ) == SBool.False.ToString() Casting error is correct btw
  • 这个演员阵容很可能是个例外(string)Session["variable"]
  • @Lanorkin:如果我没记错的话(string) 不应该抛出异常;如果 Session["var"] 无效,它将简单地返回 "" - citation @DJKRAZE:关键是不必每次都使用 ToString。这就是为什么我首先使用隐式转换。
  • @FireSBurnsmuP Session 可能包含绝对任何类型的对象,因此您可以轻松获得 InvalidCastException。只需将您的表达式分成两行并检查哪一行抛出异常

标签: c# casting asp.net-4.0 implicit


【解决方案1】:

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

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

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

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

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

会正常工作的。

【讨论】:

  • +1,如果您实现从objectSBool 的隐式转换,它会启用隐式拆箱吗?可能不会......对于编译器来说会很昂贵,副作用等等。
  • @Jodrell 这是一个类,而不是一个结构,所以这里没有装箱。也就是说,没有理由不能在类型和对象之间进行转换。
  • 如果是这种情况,那么为什么我的异常会明确指出无效转换在SBoolSystem.String 之间?如果它认为它是一个object,它不会在异常消息中说它而不是SBool吗? (((对不起,消息文本应该包含在原始帖子中。))
  • @FireSBurnsmuP 正是出于我所说的原因。在运行时类型为SBool,而您正试图将其转换为String在运行时没有从SBoolString 的转换运算符,也没有办法让用户定义的运算符可以这样做。您需要确保您永远不会试图通过允许编译器在编译时找到转换运算符在运行时找到执行此操作的转换运算符>。在编译时会话值的结果是object,但在运行时它是SBool
  • @oh,对于您说会话值是字符串的编辑,您刚才提到的错误消息表明不是这样,所以我建议您检查一下。
【解决方案2】:

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

在我看来,转换为 SBool 是一种更简洁且不易出错的解决方案。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 就算他加了也没用。
    猜你喜欢
    • 2010-10-27
    • 1970-01-01
    • 2020-09-24
    • 2013-08-25
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 2017-09-18
    • 2010-12-09
    相关资源
    最近更新 更多