Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么类型推断和隐式运算符在以下情况下不起作用?_C#_.net_Generics_Type Inference_Implicit Conversion - Fatal编程技术网

C# 为什么类型推断和隐式运算符在以下情况下不起作用?

C# 为什么类型推断和隐式运算符在以下情况下不起作用?,c#,.net,generics,type-inference,implicit-conversion,C#,.net,Generics,Type Inference,Implicit Conversion,我将试着用一个例子来解释我的问题: class V<T> { public readonly Func<T> Get; public readonly bool IsConstant; V(Func<T> get, bool isConstant) { Get = get; IsConstant = isConstant; } public static implicit op

我将试着用一个例子来解释我的问题:

class V<T>
{
    public readonly Func<T> Get;
    public readonly bool IsConstant;

    V(Func<T> get, bool isConstant)
    {
        Get = get;
        IsConstant = isConstant;
    }

    public static implicit operator V<T>(T value)
    {
        return new V<T>(() => value, true);
    }

    public static implicit operator V<T>(Func<T> getter)
    {
        return new V<T>(getter, false);
    }
}

void DoSomething<T>(V<T> v)
{
    //...
}

void Main()
{
    DoSomething<string>("test"); // (1) type inference is not working
    DoSomething<string>((V<string>)(() => "test")); // (2) implicit operator does not work
}
V类
{
公共只读Func-Get;
公共只读文件是常数;
V(函数获取,布尔值为常数)
{
得到=得到;
IsConstant=IsConstant;
}
公共静态隐式运算符V(T值)
{
返回新的V(()=>值,true);
}
公共静态隐式运算符V(Func getter)
{
返回新的V(getter,false);
}
}
无效剂量测定法(V)
{
//...
}
void Main()
{
DoSomething(“test”);/(1)类型推断不起作用
DoSomething((V)(()=>“test”);/(2)隐式运算符不起作用
}
在方法
Main
中,我有两种情况:

  • 我必须明确地为方法
    DoSomething
    指定泛型参数
  • 在这里,我必须添加显式cast
    (V)
    ,隐式操作符似乎不起作用

  • 为什么需要这样做?编译器正在考虑哪些替代方案,因此无法选择正确的方法?

    我假设您的代码打算调用DoSomething,而不是DumpValue

    你的问题是,首先,为什么

    DoSomething("");
    
    不能推断该呼叫是为了

    DoSomething<string>((V<string>)"");
    
    DoSomething((V)”;
    
    对吗

    “为什么”的问题很难回答,“为什么不?”的问题更难回答。相反,我将回答一个可以回答的问题:规范的哪一行证明了这种行为?

    重载解析的工作原理如下:如果方法组包含泛型方法,但未提供泛型方法类型参数,则类型推断将尝试推断类型参数。如果无法推断类型参数,则将从重载解析的考虑中删除该方法。在您的情况下,由于方法组中只有一个方法,删除它将导致重载解析失败

    那么为什么类型推断会失败呢?无法推断T,因为规范的控制线为:

    如果V是一个构造类型
    C
    ,并且有一组唯一的类型U1…Uk,因此存在从U到
    C
    的标准隐式转换,则从每个Ui对相应Vi进行精确推断

    没有从
    string
    V
    标准隐式转换。这是用户定义的隐式转换。

    因此类型推断失败


    我会在第二个答案中回答你的第二个问题。总的来说,一次问两个问题是个坏主意。当您有两个问题时,请发布两个问题。

    您的第二个问题是,为什么从
    ()=>“
    V
    的隐式转换没有成功,即使
    ()=>”
    可以转换为
    Func
    ,并且
    Func
    可以转换为
    V

    同样,我不知道如何回答“为什么不?”的问题,但我知道如何回答“规范的哪一行指示编译器应该拒绝此代码?”的问题,相关的行是:

    首先,如果需要,执行从用户定义或提升的转换运算符的源类型到操作数类型的标准转换

    注意这里有一个小错误;也就是说,从源表达式执行标准转换。源表达式可能没有类型。我相信在我离开团队之前,我已经给了规范维护者这个提示,所以希望这会在下一版本中得到修复

    不管怎样,现在应该清楚这里发生了什么。从lambda到委托类型没有标准的转换,因此用户定义的转换被转换解析算法归类为不适用。

    我知道你的问题是“为什么类型推断不起作用”,但我只是想在最后谈谈你关于两种选择的陈述。在这种情况下,我认为隐式转换(eww do I hate That That That That That That That That That That That That That That That That That That That That That That That That That That That That That That That。在我看来,调用
    DumpValue
    时语法会更好

    static class VFactory
    {
        public static V<T> Create<T>(T value)
        {
            return new V<T>(() => value, true);
        }
    
        public static V<T> Create<T>(Func<T> getter)
        {
            return new V<T>(getter, false);
        }
    }
    
    class V<T>
    {
        public readonly Func<T> Get;
        public readonly bool IsConstant;
    
        internal V(Func<T> get, bool isConstant)
        {
            Get = get;
            IsConstant = isConstant;
        }
    }
    
    void DumpValue<T>(V<T> v)
    {
        //...
    }
    
    void Main()
    {
        DumpValue(VFactory.Create("test"));
        DumpValue(VFactory.Create(() => "test"));
    }
    
    静态类VFactory
    {
    公共静态V创建(T值)
    {
    返回新的V(()=>值,true);
    }
    公共静态V创建(Func getter)
    {
    返回新的V(getter,false);
    }
    }
    第五类
    {
    公共只读Func-Get;
    公共只读文件是常数;
    内部V(函数获取,布尔常量)
    {
    得到=得到;
    IsConstant=IsConstant;
    }
    }
    无效转储值(V)
    {
    //...
    }
    void Main()
    {
    DumpValue(VFactory.Create(“test”);
    DumpValue(VFactory.Create(()=>“test”);
    }
    
    我的猜测:(1)编译器在知道要转换到的类型之前不会执行隐式转换,这是必要的。(2) lambda表达式没有像Func这样的特定委托类型,编译器看不到潜在的隐式强制转换。(1)确定。(2) 你说得对,投(Func)就足够了。把它作为一个答案:)Main不调用DoSoemthing;它调用了其他一些方法DumpValue。很抱歉问了一些“为什么”的问题:)作为一个非常懒惰的程序员,我更喜欢DRY。因此,如果我必须明确地说些什么,我想知道原因:)Eric,也许你可以看看这个问题,它与这个问题相关(我认为)(还涉及泛型类型推断和隐式用户定义运算符)。这不是我的问题,但我对答案感兴趣,我担心除了你们之外,这里没有人能为这样的问题提供答案:)