编译器取代了明确的投我自己的类型有明确的转换到.NET类型? [英] Compiler replaces explicit cast to my own type with explicit cast to .NET type?

查看:134
本文介绍了编译器取代了明确的投我自己的类型有明确的转换到.NET类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

 公共结构民< T> 
{
私人只读牛逼_Value;

公民(T值)
{
_Value =价值;
}

静态公共明确运营商民< T>(T值)
{
返回新的民< T>(值);
}
}

...
双D = 2.5;
&民LT;字节> B =(民<位>)D;

这代码编译,而且我的惊喜。显式转换应该只接受字节,而不是双击。但双莫名其妙地接受。当我把一个断点转换里面,我看到已经是字节值为 2 。 。通过从双转换为字节应该是明确的。



如果我编译我的EXE与ILSpy,我看到了下面的代码:

 双D = 2.5; 
Program.Num<位> B =(字节)D;



我的问题是:哪里是额外的强制转换为字节来自何处?这是为什么额外投的地方吗?我投在哪里做,以民<字节>



修改
的结构民< T> 是完整的结构,所以没有更多的隐藏额外的方法或运营商



修改结果
的IL,按要求:

  IL_0000: NOP 
IL_0001:ldc.r8 2.5 //将双2.5。
IL_000a:stloc.0
IL_000b:ldloc.0
IL_000c:// conv.u1再次明确强制转换为字节。
IL_000d:调用值类型GeneriCalculator.Program / Num`1℃的>值类型GeneriCalculator.Program / Num`1<&UINT8 GT; :: op_Explicit(0!)
IL_0012:stloc.1
IL_0013:RET


解决方案

让我们退后一步,问了一些澄清的问题:




这是程序合法。




 公共结构民< T> 
{
私人只读牛逼_Value;

公民(T值)
{
_Value =价值;
}

静态公共明确运营商民< T>(T值)
{
返回新的民< T>(值);
}
}

类节目
{
静态无效的主要()
{
双D = 2.5;
&民LT;字节> B =(民<位>)D;
}
}






你能解释为什么演员是合法的吗?




肯健指出, ,我解释说,在这里:



http://blogs.msdn.com/b/ericlippert/archive/2007/04/16/chained-user-defined-explicit-conversions-in-c的.aspx



简单地说:一个用户定义的显式转换可能会在插入两端内置的显示转换。也就是说,我们可以插入一个显式转换无论是从源表达的参数类型的用户定义转换方法的,或者从用户定义的转换方法转换的目标类型的返回类型。 (或者,在某些罕见的情况下,无论是。)



在这种情况下,我们插入一个内置的显式转换参数类型,字节,所以你的程序是一样的因为如果你会写:

 民<位> B =(民<位>)(字节)D; 

这是可取的行为。双可能被显式转换为字节,所以双也可以显式转换为民<位>



有关完整的说明,请阅读6.4.5节中的C#4规范的用户自定义显式转换。




为什么白细胞介素生成调用 op_Implicit 而不是 op_Explicit




它没有;这个问题的前提是一个谎言。以上程序生成:

  IL_0000:NOP 
IL_0001:ldc.r8 2.5
IL_000a:stloc。 0
IL_000b:ldloc.0
IL_000c:conv.u1
IL_000d:调用值类型Num`1℃的>值类型Num`1<&UINT8 GT; :: op_Explicit(0!)
IL_0012:stloc.1
IL_0013:RET

您正在寻找一个老版本可能是你的计划。做一个干净的重建。




有没有在C#编译器默默插入一个显式转换的其他情况?




是的;其实这是第二次这个问题今天已经上来了。见



C#类型转换不一致?


I have the following code:

public struct Num<T>
{
    private readonly T _Value;

    public Num(T value)
    {
        _Value = value;
    }

    static public explicit operator Num<T>(T value)
    {
        return new Num<T>(value);
    }
}

...
double d = 2.5;
Num<byte> b = (Num<byte>)d;

This code compiles, and it surprises my. The explicit convert should only accept a byte, not a double. But the double is accepted somehow. When I place a breakpoint inside the convert, I see that value is already a byte with value 2. By casting from double to byte should be explicit.

If I decompile my EXE with ILSpy, I see the next code:

double d = 2.5;
Program.Num<byte> b = (byte)d;

My question is: Where is that extra cast to byte coming from? Why is that extra cast place there? Where did my cast to Num<byte> go to?

EDIT
The struct Num<T> is the entire struct, so no more hidden extra methods or operators.

EDIT
The IL, as requested:

IL_0000: nop
IL_0001: ldc.r8 2.5 // Load the double 2.5.
IL_000a: stloc.0
IL_000b: ldloc.0
IL_000c: conv.u1 // Once again the explicit cast to byte.
IL_000d: call valuetype GeneriCalculator.Program/Num`1<!0> valuetype GeneriCalculator.Program/Num`1<uint8>::op_Explicit(!0) 
IL_0012: stloc.1
IL_0013: ret

解决方案

Let's take a step back and ask some clarifying questions:

Is this program legal?

public struct Num<T>
{
    private readonly T _Value;

    public Num(T value)
    {
        _Value = value;
    }

    static public explicit operator Num<T>(T value)
    {
        return new Num<T>(value);
    }
}

class Program
{
    static void Main()
    {
        double d = 2.5;
        Num<byte> b = (Num<byte>)d;
    }
}

Yes.

Can you explain why the cast is legal?

As Ken Kin pointed out, I explain that here:

http://blogs.msdn.com/b/ericlippert/archive/2007/04/16/chained-user-defined-explicit-conversions-in-c.aspx

Briefly: a user-defined explicit conversion may have a built-in explicit conversion inserted on "both ends". That is, we can insert an explicit conversion either from the source expression to the parameter type of the user-defined conversion method, or from the return type of the user-defined conversion method to the target type of the conversion. (Or, in some rare cases, both.)

In this case we insert a built-in explicit conversion to the parameter type, byte, so your program is the same as if you'd written:

        Num<byte> b = (Num<byte>)(byte)d;

This is desirable behaviour. A double may be explicitly converted to byte, so a double may also be explicitly converted to Num<byte>.

For a complete explanation, read section 6.4.5 "User-defined explicit conversions" in the C# 4 specification.

Why does the IL generated call op_Implicit instead of op_Explicit?

It doesn't; the question is predicated on a falsehood. The above program generates:

  IL_0000:  nop
  IL_0001:  ldc.r8     2.5
  IL_000a:  stloc.0
  IL_000b:  ldloc.0
  IL_000c:  conv.u1
  IL_000d:  call       valuetype Num`1<!0> valuetype Num`1<uint8>::op_Explicit(!0)
  IL_0012:  stloc.1
  IL_0013:  ret

You're looking at an old version of your program probably. Do a clean rebuild.

Are there other situations in which the C# compiler silently inserts an explicit conversion?

Yes; in fact this is the second time that question has come up today. See

C# type conversion inconsistent?

这篇关于编译器取代了明确的投我自己的类型有明确的转换到.NET类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆