铸造和使用Convert.To()方法之间的区别 [英] Difference between casting and using the Convert.To() method

查看:432
本文介绍了铸造和使用Convert.To()方法之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有关于字符串价值观蒙上了双击的功能。

I have a function that casts a double on string values.

string variable = "5.00"; 

double varDouble = (double)variable;

一个code修改是在检查,生成项目,并出现错误: System.InvalidCastException:指定的转换是无效

A code change was checked in and the project builds with the error: System.InvalidCastException: Specified cast is not valid.

但是,这样做之后,下面...

However, after doing the following...

string variable = "5.00"; 

double varDouble = Convert.ToDouble(variable);

...生成项目没有任何错误。

...the project builds without any errors.

什么是铸造和使用 Convert.To()方法之间的区别?为什么铸造抛出异常,并使用 Convert.To()不?

What is the difference between casting and using the Convert.To() method? Why does casting throw an Exception and using the Convert.To() does not?

推荐答案

即使你的可能的看到他们在某种程度上等同他们在目的完全不同。让我们先尝试定义铸造是什么:

Even if you may see them somehow as equivalent they're completely different in purpose. Let's first try to define what a cast is:

铸造是改变一个数据类型的实体到另一个的动作。

Casting is the action of changing an entity of one data type into another.

这是有点通用的,它在某种程度上相当于一个的转换,因为投有一个转换往往相同的语法,所以问题应该是:当铸造(隐性或显性)被允许的语言时,你必须使用一个(更多)显式转换?

It's little bit generic and it's somehow equivalent to a conversion because cast has often same syntax of a conversion so the question should be when a cast (implicit or explicit) is allowed by the Language and when you have to use a (more) explicit conversion?

首先,让我的的他们之间的简单线条,正式(即使相当于语言的语法)浇注将改变类型,而转换会/可能改变值(最终的一起用型)。也投是可逆的,而转换可能不。

Let me first draw a simple line between them, formally (even if equivalent for language syntax) a cast will change type while a conversion will/may change value (eventually together with type). Also cast is reversible while conversion may not be.

主题是pretty vaste,让我们试着拉近一点点,从本场比赛第一个我们排除自投的运营商。

Topic is pretty vaste, let's try to narrow a little bit, at first we exclude custom cast operators from the game.

在C#中的演员阵容的隐时你不会丢失任何信息(请注意,此检查执行与类型,而不是与它们的实际值

In C# a cast is implicit when you won't lose any information (please note that this check is performed with types and not with their actual values).

例如:

int tinyInteger = 10;
long bigInteger = tinyInteger;

float tinyReal = 10.0f;
double bigReal = tinyReal;

这些类型转换是隐式的,因为你不会丢失任何信息在转换过程中(你只是做了更广泛的类型)。反之亦然隐式转换是不是因为允许的,不管它们的实际值(因为它们只能在运行时进行检查),转换过程中可能会丢失一些信息。例如,这code不能编译,因为一个双击可能含有(实际上它)的值不以浮动:

These casts are implicit because during the conversion you won't lose any information (you just make the type wider). Vice versa implicit cast isn't allowed because, regardless their actual values (because they can be checked only at run-time), during conversion you may lose some information. For example this code won't compile because a double may contain (and actually it does) a value not representable with a float:

double bigReal = Double.MaxValue;
float tinyReal = bigReal;

对象

在一个对象(指针)的演员总是隐含的编译器可以肯定的是,源类型是一个派生类(或实现)目标类的类型,例如时:

Objects

In case of an object (a pointer to) the cast is always implicit when the compiler can be sure that the source type is a derived class (or it implements) the type of the target class, for example:

string text = "123";
IFormattable formattable = text;

NotSupportedException derivedException = new NotSupportedException();
Exception baseException = derivedException;

在这种情况下,编译器的知道的是字符串工具 IFormattable 引发NotSupportedException 是(从派生)例外这样的转换是隐含的。不丢失任何信息,因为对象不改变它们的类型(这是结构不同来源和原始类型,因为有投你创建另一种类型的新对象),什么样的变化是你的视图的他们。

In this case the compiler knows that string implements IFormattable and that NotSupportedException is (derives from) Exception so the cast is implicit. No information is lost because objects doesn't change their types (this is different with structs and primitive types because with a cast you create a new object of another type), what changes is your view of them.

当转换不是由编译器隐式完成,则必须使用转换运算符强制转换为显性。通常这意味着:

A cast is explicit when the conversion isn't done implicitly by the compiler and then you must use the cast operator. Usually it means that:


  • ,所以你必须要知道的是,您可能会丢失信息或数据。

  • 转换可能会失败(因为你不能在一个类型转换为其他的),因此,再次,你必须知道你在做什么。

需要显式强制转换为原始类型时,转换过程中可能会丢失一些数据,例如:

An explicit cast is required for primitive types when during conversion you may lose some data, for example:

double precise = Math.Cos(Math.PI * 1.23456) / Math.Sin(1.23456);
float coarse = (float)precise;

float epsilon = (float)Double.Epsilon;

在这两个例子中,即使值在浮在范围内,你就会失去信息(在这种情况下,precision),因此在转换必须明确。现在试试这个:

In both examples, even if values fall within the float range, you'll lose information (in this case precision) so the conversion must be explicit. Now try this:

float max = (float)Double.MaxValue;

此转换将失败的话,再次,它必须是明确的,所以你是意识到这一点,你可以做一个检查(在本例中值是恒定的,但它可能来自一些运行时计算或I / O) 。回到你的例子:

This conversion will fail so, again, it must be explicit so you're aware of it and you may do a check (in the example value is constant but it may come from some run-time computations or I/O). Back to your example:

string text = "123";
double value = (double)text;

这不能编译,因为编译器无法文本转换为数字。文本可能包含任何字符,不仅是数字,这实在是太多了,在C#中,即使有明确的转换(但可能在另一种语言被允许)。

This won't compile because compiler can't convert text to numbers. Text may contains any characters, not numbers only and this is too much, in C#, even for an explicit cast (but it may be allowed in another language).

如果类型是不相关的,例如该code不会编译(因为编译器知道有没有可能转换)转换从指针(对象)可能会失败:

Conversion from pointers (to objects) may fail if types are unrelated, for example this code won't compile (because compiler knows there is no possible conversion):

string text = (string)AppDomain.Current;
Exception exception = (Exception)"abc";

这code将编译,但它可能会在运行时(这取决于有效型铸造的对象)与失败 InvalidCastException的

This code will compile but it may fail at run-time (it depends on the effective type of casted objects) with an InvalidCastException:

object obj = GetNextObjectFromInput();
string text = (string)obj;

obj = GetNextObjectFromInput();
Exception exception = (Exception)obj;

转化

所以,最后,如果强制类型转换是转换那么,为什么我们需要一个像类转换需要?忽略来自转换细微的差别实施和 IConvertible 的实施实际上是因为在C#与你的编译器说投:

Conversions

So, finally, if casts are conversion then why we need classes like Convert are needed? Ignoring subtle differences that comes from Convert implementation and IConvertible implementations actually because in C# with a cast you say to the compiler:

相信我,这类型的类型,即使你不知道现在,让我做它,你会看到的。

- 或 -

不用担心,我不在乎的东西会迷失在这个转换。

有关其他任何东西的更多的需要显式操作(想想的容易蒙上的的影响,这就是为什么C ++引入长,冗长和明确的语法为他们)。这可能涉及复杂的操作(字符串 - > 双击转换将需要一个解析)。转换为字符串,例如,始终是可能的(通过的ToString()方法),但它可能意味着什么不同你所期望的,因此必须比铸造更明确(更多你写的,你越多想想你在做什么)。

For anything else a more explicit operation is needed (think about implications of easy casts, that's why C++ introduced long, verbose and explicit syntax for them). This may involve a complex operation (for string -> double conversion a parsing will be needed). Conversion to string, for example, is always possible (via ToString() method) but it may mean something different from what you expect so it must be more explicit than a cast (more you write, more you think about what you're doing).

这转换可以在物体内进行(使用的已知IL指令),使用自定义转换操作符(定义在类中投)或更复杂的机制(的TypeConverter s或类方法,例如)。你不知道会发生这样做什么,但你知道它可能会失败(这就是为什么当更多的控制的IMO转换是可能的,你应该使用它)。在你的情况下,转换只是将解析字符串来产生双击

This conversion can be done inside the object (using known IL instructions for that), using custom conversion operators (defined in the class to cast) or more complex mechanisms (TypeConverters or class methods, for example). You're not aware of what will happen to do that but you're aware it may fail (that's why IMO when a more controlled conversion is possible you should use it). In your case the conversion simply will parse the string to produce a double:

double value = Double.Parse(aStringVariable);

当然,这可能会失败,所以如果你这样做,你应该始终抓住它可能会抛出异常( FormatException )。这是在这里的话题,但如果当的TryParse 可用,那么你应该使用它(因为语义上你的的它可能不是一个数字,它是甚至更快...失败)。

Of course this may fail so if you do it you should always catch the exception it may throw (FormatException). It's out of topic here but if when a TryParse is available then you should use it (because semantically you say it may not be a number and it's even faster...to fail).

在.NET转换可以来自很多地方,的TypeConverter ,隐/显式转换用户定义的转换操作符,实施 IConvertible 和解析的方法(我也不曾忘记的东西吗?)。以获取更多相关细节在MSDN上看看。

Conversions in .NET can come from a lot of places, TypeConverter, implicit/explicit casts with user defined conversion operators, implementation of IConvertible and parsing methods (did I forget something?). Take a look on MSDN for more details about them.

要完成这个长回答有关用户自定义转换操作符只是几句话。这只是的的糖的让程序员使用强制转换为一种类型转换为另一种。这是一类,说:哎,如果他/她想要这种类型转换为类型,然后我能做到(将铸造的)里面的方法。例如:

To finish this long answer just few words about user defined conversion operators. It's just sugar to let the programmer use a cast to convert one type to another. It's a method inside a class (the one that will be casted) that says "hey, if he/she wants to convert this type to that type then I can do it". For example:

float? maybe = 10; // Equals to Nullable<float> maybe = 10;
float sure1 = (float)maybe; // With cast
float sure2 = maybe.Value; // Without cast

在这种情况下,这是明确的,因为它可能会失败,但是这是让到实现(即使有这个准则)。想象一下,你写了一个自定义字符串类是这样的:

In this case it's explicit because it may fail but this is let to the implementation (even if there are guidelines about this). Imagine you write a custom string class like this:

EasyString text = "123"; // Implicit from string
double value = (string)text; // Explicit to double

在您的实现您可能会决定做程序员的生活更轻松,并通过投揭露这种转换(记住,这只是一个快捷方式到少写)。有些语言甚至可能会允许这样的:

In your implementation you may decide to "make programmer's life easier" and to expose this conversion via a cast (remember it's just a shortcut to write less). Some Language may even allow this:

double value = "123";

允许隐式转换的任何类型(支票将在运行时进行)。有了正确的选项可以做到这一点,例如,在VB.NET。这只是一个不同的哲学思想。

Allowing implicit conversion to any type (check will be done at run-time). With proper options this can be done, for example, in VB.NET. It's just a different phylosophy.

所以最终的问题是,什么时候应该使用一种或另一种。让我们来看看时,你可以使用一个明确的转换:

So the final question is when you should use one or another. Let's see when you can use an explicit cast:


    基本类型之间的
  • 转化。

  • 转化对象任何其他类型的(这可能包括拆箱太)。

  • 从派生类
  • 转化为一个基类(或实现接口)。

  • 通过自定义转换操作符
  • 转换从一种类型到另一个。

  • Conversions between base types.
  • Conversions from object to any other type (this may include unboxing too).
  • Conversions from a derived class to a base class (or to an implemented interface).
  • Conversions from one type to another via custom conversion operators.

只有第一个转换可以用进行转换所以换了别人,你没有选择,你需要使用显式的转换。

Only the first conversion can be done with Convert so for the others you have no choice and you need to use an explicit cast.

让我们看看时,你可以使用转换

Let's see now when you can use Convert:


    从任何基本类型到另一个基站类型
  • 转化(有一些限制,请参见<一个href=\"http://msdn.microsoft.com/en-us/library/vstudio/system.convert%28v=vs.90%29.aspx\">MSDN).

  • 从任何类型的
  • 转化实现 IConvertible 其他任何(支持)型。

  • 从/到字节阵列/从字符串
  • 转化。

  • Conversions from any base type to another base type (with some limitations, see MSDN).
  • Conversions from any type that implements IConvertible to any other (supported) type.
  • Conversions from/to a byte array to/from a string.

IMO 转换应在每次知道一个转换可能会失败(因为格式的,因为范围,或者因为它可能是不支持的)时使用,即使是同一转换可以用铸件来完成(除非别的东西可用)。 这昭示谁将会阅读你的code什么是你的意图,它可能会失败(简化调试)。

IMO Convert should be used each time you know a conversion may fail (because of format, because of range or because it may be unsupported), even if the same conversion can be done with a cast (unless something else is available). It makes clear to who will read your code what's your intent and that it may fail (simplifying debug).

有关一切你需要使用一个演员,没有选择,但如果另一个更好的方法是可行的话,我建议你使用它。在您的例子从字符串来转换双击的东西,(特别是如果文本来自用户)经常会失败所以你应该使用的TryParse 方法,使其尽可能多的明确越好(而且你得到了它更多的控制),例如。

For everything else you need to use a cast, no choice, but if another better method is available then I suggest you use it. In your example a conversion from string to double is something that (especially if text comes from user) very often will fail so you should make it as much explicit as possible (moreover you get more control over it), for example using a TryParse method.

根据更新的问题,保持了我以前写(约的的你可以使用强制转换时相比,你可以/必须使用转换),那么最后一点澄清的是,如果有他们(而且转换使用 IConvertible 和<$ C $的区别C> IFormattable 接口,所以它可以执行不得与强制转换操作)。

According to updated question and keeping what I wrote before (about when you can use a cast compared to when you can/have to use Convert) then last point to clarify is if there are difference between them (moreover Convert uses IConvertible and IFormattable interfaces so it can perform operations not allowed with casts).

简短的答案是是,它们的行为不同即可。我看转换类像一个辅助方法门课常常它提供了一些的好处的或稍有不同的行为。例如:

Short answer is yes, they behave different. I see the Convert class like a helper methods class so often it provides some benefit or slightly different behaviors. For example:

double real = 1.6;
int castedInteger = (int)real; // 1
int convertedInteger = Convert.ToInt32(real); // 2

pretty不同的,对不对?铸造截断(这是我们都期望),但转换进行四舍五入到最接近的整数(如果你没有意识到这一点,这可能无法预期)。每个转换方法引入分歧,一般的规则不能被应用,它们必须被视为逐案... 19基本类型转换到所有其他类型...列表可以是pretty长,好多咨询MSDN逐案!

Pretty different, right? Cast truncates (it's what we all expect) but Convert performs a rounding to nearest integer (and this may not be expected if you're not aware of it). Each conversion method introduces differences so a general rule can't be applied and they must be seen case by case...19 base types to convert to every other type...list can be pretty long, much better to consult MSDN case by case!

这篇关于铸造和使用Convert.To()方法之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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