【问题标题】:Prevent implicit cast to int when asking for Expression<Func<T, decimal>>在请求 Expression<Func<T, decimal>> 时防止隐式转换为 int
【发布时间】:2019-09-09 22:19:44
【问题描述】:

因此,int 可以隐式转换为 decimal。当需要 decimal 属性的 Expression 时,这会导致问题,其中传递了具有隐式转换的 int 属性的 Expression。由于隐式转换,没有给出编译器错误。

例如:

class Thing {
   public int IntProperty { get; set; }
}

void DoSomething(
   Expression<Func<Thing, decimal>> pDecimalExpression
) {
   ...
}

DoSomething(t => t.IntProperty); // compiles; IntProperty is implicitly cast to decimal

有没有办法在编译时确保我真的得到了decimal 属性?如果我像这样传递一个带有隐式转换的表达式,我想要一个编译器错误。

(由于我使用反射,我最终得到一个运行时错误,说我正在使用的属性不能被赋予decimal 值。我觉得我能做的最好的就是检测类型不匹配我自己在运行时并抛出一个稍微好一点的错误。)

【问题讨论】:

    标签: c#


    【解决方案1】:

    我会使用通用约束。由于struct类型不能直接使用,你仍然可以使用IEquatable&lt;T&gt;来限制可以作为T传递的内容(内置类型实现了这个接口)。缺点是任何实现IEquatable&lt;decimal&gt; 的东西都将被允许作为T 通用参数(在您的情况下可能会或不会出现问题)。

    void DoSomething<T>(Expression<Func<Thing, T>> pDecimalExpression)
        where T : struct, IEquatable<decimal> {
        ...
    }
    

    第二种选择是编写自定义 Roslyn Analyzer 以在编译时验证代码。

    希望对你有帮助。

    【讨论】:

    • 我最终采用了这种方法。我不喜欢让我的方法不必要地通用,而且我还不得不在Tdecimal 之间进行转换,但最好不要编写额外的方法。
    • 你到底在处理什么?我可以看看它,希望能给你一个更新来解决它。
    • 我使用此处找到的解决方案解决了转换问题:stackoverflow.com/a/26098316/621316
    • @DaveCousineau:我现在坐在上面。只是给我更多的上下文。您只需要设置值还是需要做更多的事情?
    • 我没有其他问题。这很好用。我不喜欢这些方法是通用的,但它肯定比以前更好。现在一切正常,如果我提供 int 属性,我将收到编译器错误。
    【解决方案2】:

    您可以使用一个技巧。编译器会更喜欢int 的重载,因此提供一个重载并使用ObsoleteAttribute's 发出编译时错误的能力。

    像这样声明DoSomething

    void DoSomething(Expression<Func<Thing, decimal>> pDecimalExpression)
    {
        // …
    }
    
    [Obsolete("No, no, no!", true)] // the true here causes an error instead of a warning
    void DoSomething(Expression<Func<Thing, int>> pIntExpression)
    {
        // just in case someone would call this method via reflection
        throw new NotSupportedException();
    }
    

    以下调用会导致编译时错误:

    DoSomething(t => t.IntProperty);
    

    【讨论】:

    • 谢谢!我想过重载,但只是想出了调用仍然会转换的另一个版本(如果我什至可以调用它的话),或者只是抛出一个已经发生的异常。
    猜你喜欢
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-20
    相关资源
    最近更新 更多