不能隐式地将类型'X'转换为'string' - 何时以及如何判断它“不能”?

时间:2020-12-26 16:32:56

Right now I'm having it with Guids.

现在,我正在使用Guids。

I certainly remember that throughout the code in some places this implicit conversion works, in others it does not. Until now I fail to see the pattern.

我当然记得,在某些地方的代码中,这种隐式转换是有效的,而在其他地方则没有。直到现在我都没有看到这种模式。

How the compiler decides when it cannot? I mean, the type method Guid.ToString() is present, isn't it called whenever this transformation is needed?

编译器如何决定它何时不能?我的意思是,类型方法Guid.ToString()存在,不需要在需要这种转换时调用它吗?

Can someone please tell me under what circumstances this transformation is done automatically and when I have to call myInstance.ToString() explicitly?

有人可以告诉我在什么情况下这个转换是自动完成的,当我必须显式调用myInstance.ToString()时?

3 个解决方案

#1


In short, when there is an implicit or explicit conversion operator defined:

简而言之,当定义了隐式或显式转换运算符时:

class WithImplicit {
    public static implicit operator string(WithImplicit x) {
        return x.ToString();}
}
class WithExplicit {
    public static explicit operator string(WithExplicit x) {
        return x.ToString(); }
}
class WithNone { }

class Program {
    static void Main() {
        var imp = new WithImplicit();
        var exp = new WithExplicit();
        var none = new WithNone();
        string s1 = imp;
        string s2 = (string)exp;
        string s3 = none.ToString();
    } 
}

#2


No, there is no implicit conversion from GUID to String, so that doesn't work anywhere at all in the code.

不,没有从GUID到String的隐式转换,因此在代码中根本不起作用。

It only works where there is an explicit conversion, but the conversion might not be very visible. For example when you concatenate strings:

它仅适用于存在显式转换的情况,但转换可能不是非常明显。例如,当您连接字符串时:

string id = "--" + guidValue + " : " + num;

This may look like an implicit conversion from GUID to String, but it isn't. The code that is generated actually looks like this:

这可能看起来像是从GUID到String的隐式转换,但事实并非如此。生成的代码实际上如下所示:

string id = String.Concat(new object[] { "--", guidValue, " : ", num });

All operands are cast to the type Object and placed in an array. The String.Concat method then calls the ToString method for each item in the array to get the string representation for them.

所有操作数都转换为Object类型并放在一个数组中。然后,String.Concat方法为数组中的每个项调用ToString方法,以获取它们的字符串表示形式。

#3


The only place where you effectively don't need to call ToString() yourself is when concatenating strings.

你自己实际上不需要自己调用ToString()的唯一地方就是串联字符串。

Guid g;
int i;
string s = "Hello "+g+' '+i;

Then there are some situations where the call is made by the .NET Framework, such as in String.Format().

然后在某些情况下,.NET Framework会进行调用,例如在String.Format()中。

Other than that, the compiler will only convert a type if it is known to be compatible (e.g. base class or implementing an interface or via an explicitly coded conversion operator). When you use a cast and the compiler knows that the types cannot be compatible (e.g. not in the same inheritance line, and not interfaces), it will also say that it cannot convert it. The same goes for generic type parameters.

除此之外,编译器将仅在已知兼容的情况下转换类型(例如,基类或实现接口或通过显式编码的转换运算符)。当您使用强制转换并且编译器知道类型不能兼容时(例如,不在同一继承行中,而不是接口),它也会说它无法转换它。通用类型参数也是如此。

#1


In short, when there is an implicit or explicit conversion operator defined:

简而言之,当定义了隐式或显式转换运算符时:

class WithImplicit {
    public static implicit operator string(WithImplicit x) {
        return x.ToString();}
}
class WithExplicit {
    public static explicit operator string(WithExplicit x) {
        return x.ToString(); }
}
class WithNone { }

class Program {
    static void Main() {
        var imp = new WithImplicit();
        var exp = new WithExplicit();
        var none = new WithNone();
        string s1 = imp;
        string s2 = (string)exp;
        string s3 = none.ToString();
    } 
}

#2


No, there is no implicit conversion from GUID to String, so that doesn't work anywhere at all in the code.

不,没有从GUID到String的隐式转换,因此在代码中根本不起作用。

It only works where there is an explicit conversion, but the conversion might not be very visible. For example when you concatenate strings:

它仅适用于存在显式转换的情况,但转换可能不是非常明显。例如,当您连接字符串时:

string id = "--" + guidValue + " : " + num;

This may look like an implicit conversion from GUID to String, but it isn't. The code that is generated actually looks like this:

这可能看起来像是从GUID到String的隐式转换,但事实并非如此。生成的代码实际上如下所示:

string id = String.Concat(new object[] { "--", guidValue, " : ", num });

All operands are cast to the type Object and placed in an array. The String.Concat method then calls the ToString method for each item in the array to get the string representation for them.

所有操作数都转换为Object类型并放在一个数组中。然后,String.Concat方法为数组中的每个项调用ToString方法,以获取它们的字符串表示形式。

#3


The only place where you effectively don't need to call ToString() yourself is when concatenating strings.

你自己实际上不需要自己调用ToString()的唯一地方就是串联字符串。

Guid g;
int i;
string s = "Hello "+g+' '+i;

Then there are some situations where the call is made by the .NET Framework, such as in String.Format().

然后在某些情况下,.NET Framework会进行调用,例如在String.Format()中。

Other than that, the compiler will only convert a type if it is known to be compatible (e.g. base class or implementing an interface or via an explicitly coded conversion operator). When you use a cast and the compiler knows that the types cannot be compatible (e.g. not in the same inheritance line, and not interfaces), it will also say that it cannot convert it. The same goes for generic type parameters.

除此之外,编译器将仅在已知兼容的情况下转换类型(例如,基类或实现接口或通过显式编码的转换运算符)。当您使用强制转换并且编译器知道类型不能兼容时(例如,不在同一继承行中,而不是接口),它也会说它无法转换它。通用类型参数也是如此。