c# - 当使用 long 作为参数时,为什么在 long、float 和 decimal 方法之间存在模棱两可的方法调用?

标签 c# npgsql c#-8.0

我正在尝试构建 NpgsqlSimpleTypeHandler<ulong>处理转换 ulong值为 long值,以便它们可以存储在我的 PostgreSQL 数据库中,反之亦然。
当我尝试调用 Npgsql 的 Int64handler.ValidtaeAndGetLength转换后 ulonglongConvert.ToInt64(value) ,试图通过新转换的 long给我一个模棱两可的方法调用错误。

private readonly Int64Handler handler;
...
public override int ValidateAndGetLength(ulong value, NpgsqlParameter? parameter)
{
    long val = Convert.ToInt64(value);
    return handler.ValidateAndGetLength(val, parameter);
}
错误信息:
Error   CS0121
The call is ambiguous between the following methods or properties:
'Int64Handler.ValidateAndGetLength(float, NpgsqlParameter?)' and
'Int64Handler.ValidateAndGetLength(decimal, NpgsqlParameter?)'
为什么,即使使用 Int64Handler.ValidateAndGetLength(long, NpgsqlParameter?)现有的,我是否会遇到模棱两可的方法调用错误?
Npgsql Int64Handler documentation
[7/21/2020 14:23 EST] 更新标签以包含 C#-8.0

最佳答案

ValidateAndGetLength(long, NpgsqlParameter?) 之间的区别和 Int64Handler 中的其他重载class 是第一个方法实际上是覆盖类中的方法 NpgsqlSimpleTypeHandler<long>实现 INpgsqlSimpleTypeHandler<long> ,而其他方法正在实现 INpgsqlSimpleTypeHandler<T> 中的方法直接接口(interface)。
来自 C# 6 draft language specification :

For example, the set of candidates for a method invocation does not include methods marked override (Member lookup), and methods in a base class are not candidates if any method in a derived class is applicable (Method invocations).


“成员查找”部分对此进行了进一步扩展:

First, a set of accessible members named N is determined:

If T is a type parameter, then the set is the union of the sets of accessible members named N in each of the types specified as a primary constraint or secondary constraint (Type parameter constraints) for T, along with the set of accessible members named N in object.

Otherwise, the set consists of all accessible (Member access) members named N in T, including inherited members and the accessible members named N in object. If T is a constructed type, the set of members is obtained by substituting type arguments as described in Members of constructed types. Members that include an override modifier are excluded from the set.


我设法用示例代码重现了这个问题:
using System;

interface IA<T>
{
    int X(T x);
}

abstract class A<T> : IA<T>
{
    public abstract int X(T x);
}

class B : A<long>, IA<float>, IA<decimal>
{
    public override int X(long x)
    {
        return 8;
    }
    
    public int X(float x)
    {
        return 8;
    }
    
    public int X(decimal x)
    {
        return 8;
    }
}
                    
public class Program
{
    public static void Main()
    {
        var b = new B();
        var a = (A<long>)b;
        Console.WriteLine(a.X(42L));
        // Console.WriteLine(b.X(42L)); // broken
    }
}
您可以使用将处理程序转换为 NpgsqlSimpleTypeHandler<long> 的解决方法。并改为调用该方法。

关于c# - 当使用 long 作为参数时,为什么在 long、float 和 decimal 方法之间存在模棱两可的方法调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63020024/

相关文章:

c# - 每个显示器 DPI 感知的 WPF 应用程序与 RibbonWindow

c# - 锁定 AppendAllText 与 TextWriter

c# - asp c# 基本mailto函数

f# - 从 F# 访问显式转换运算符

c# - 如何将c#(asp.net core)日期时间保存到PostgreSQL日期

c# - PostgreSQL:在有外键的多表中插入大量

c# - LINQ GroupBy 仅在键不为空时选择

c# - 为什么 Thread.Sleep(0) 时间片处理优先级较低的线程?

c# - 如何将 NonNullable 引用属性标记为安全?

c#-8.0 - MaybeNull 属性对空引用返回发出警告