我一直在研究一些代码。我有一个问题:强制转换、解析和转换之间有什么区别?我们什么时候可以使用它们?
7 回答
强制转换是当您获取一种类型的变量并将其更改为另一种类型时。您只能在某些情况下这样做,例如:
string str = "Hello";
object o = str;
string str2 = (string)o; // <-- This is casting
强制转换不会更改变量的值 - 值保持相同类型(字符串“Hello”)。
转换是从一种类型中获取一个值并将其转换为另一种类型:
double d = 5.5;
int i = (int)d; // <---- d was converted to an integer
请注意,在这种情况下,转换是以强制转换的形式完成的。
解析是获取一个字符串并通过了解其内容将其转换为不同的类型。例如,将字符串“123”转换为数字 123,或将字符串“Saturday, September 22nd”转换为 DateTime。
Casting:告诉编译器一个对象实际上是别的东西而不改变它(尽管可能会导致一些数据丢失)。
object obj_s= "12345";
string str_i = (string) obj; // "12345" as string, explicit
int small = 12345;
long big = 0;
big = small; // 12345 as long, implicit
Parsing:告诉程序解释(在运行时)一个字符串。
string int_s = "12345";
int i = int.Parse(int_s); // 12345 as int
转换:告诉程序使用内置方法来尝试更改可能不能简单互换的类型。
double dub = 123.45;
int i = System.Convert.ToInt32(dub); // 123 as int
这是三个具有特定用途的术语:
- 铸造 - 改变一个
type
到另一个。为了做到这一点,类型必须兼容:int
->object
;IList<T>
->IEnumerable<T>
- 解析 - 通常是指读取字符串并提取有用的部分
- 转换 - 类似于强制转换,但通常转换将涉及将一种类型更改为其他不兼容的类型。一个例子是将对象转换为字符串。
从一种类型转换到另一种类型需要某种形式的兼容性,通常通过继承或实现接口。强制转换可以是隐式的或显式的:
class Foo : IFoo {
// implementations
}
// implicit cast
public IFoo GetFoo() {
return Foo;
}
// explicit cast
public IFoo GetFoo() {
return Foo as IFoo;
}
解析的方法有很多。我们阅读了 XML 解析;一些类型有Parse
和TryParse
方法;然后有时我们需要解析字符串或其他类型来提取“我们关心的东西”。
int.Parse("3") // returns an integer value of 3
int.TryParse("foo", out intVal) // return true if the string could be parsed; otherwise false
转换可能需要将一种类型更改为另一种不兼容的类型。这也可能涉及一些解析。转换示例通常与 IMO 非常相关。
不同的人用它来表示不同的东西。在 .net 世界之外不必是真的,但这是我在阅读 Eric Lippert 的博客的 .net 上下文中所理解的:
从一种形式到另一种形式的所有类型转换都可以称为转换。一种分类方式可能是
隐含的——
一个。表示改变(也称为强制)
int i = 0; double d = i; object o = i; // (specifically called boxing conversion) IConvertible o = i; // (specifically called boxing conversion)
需要隐式转换运算符,转换总是成功(隐式转换运算符永远不应该抛出),更改正在转换的对象的引用标识。
湾。表示保留(也称为隐式引用转换)
string s = ""; object o = s; IList<string> l = new List<string>();
仅对引用类型有效,从不更改被转换对象的引用标识,转换始终成功,在编译时保证,没有运行时检查。
显式(也称为强制转换)-
一个。表示变化
int i = 0; enum e = (enum)i; object o = i; i = (int)o; // (specifically called unboxing conversion)
需要显式转换运算符,更改被转换对象的引用标识,转换可能成功也可能不成功,运行时检查兼容性。
湾。表示保留 (也称为显式引用转换)
object o = ""; string s = (string)o;
仅对引用类型有效,从不更改被转换对象的引用标识,转换可能成功也可能不成功,运行时检查兼容性。
虽然转换是语言级别的构造,但Parse在框架级别的意义上是完全不同的东西,或者换句话说,它们是为从输入获取输出而编写的自定义方法int.Parse
,例如接受 astring
并返回 a int
。
强制转换(强制类型转换需要兼容) 数据类型之间的转换可以使用强制转换显式完成
static void _Casting()
{
int i = 10;
float f = 0;
f = i; // An implicit conversion, no data will be lost.
f = 0.5F;
i = (int)f; // An explicit conversion. Information will be lost.
}
parsing(解析是不同类型之间的转换:)将一种类型转换为另一种类型可以称为解析uisng int.parse
int num = int.Parse("500");
遍历XML之类的数据项也可以称为解析
当涉及到用户定义的转换时,这通常需要返回不同的对象/值。用户定义的转换通常存在于值类型而不是引用类型之间,因此这很少成为问题。
使用 Convert 类实际上只是帮助您解析它
有关更多信息,请参阅http://msdn.microsoft.com/en-us/library/ms228360%28VS.80%29.aspx
铸造:或解析
强制转换显式调用从一种类型到另一种类型的转换运算符。铸造变量并不简单。一组复杂的规则解决了强制转换。在某些情况下,数据会丢失,并且强制转换无法反转。在其他情况下,执行引擎中会引发异常。
int.Parse
是一种最简单的方法,但它会在无效输入时引发异常。
int.TryParse
是 C# 语言中解析整数的最有用的方法之一。此方法的工作方式与int.Parse
.
int.TryParse
里面有try and catch结构。所以,它不会抛出异常
将基本数据类型转换为另一种基本数据类型。Convert.ToInt32 及其兄弟 Convert.ToInt16 和 Convert.ToInt64 实际上是 int.Parse 方法的静态包装方法。
许多程序员推荐使用TryParse
代替Convert
或。Cast
这个问题其实挺复杂的……
通常,强制转换只是告诉运行时将一种类型更改为另一种类型。这些必须是兼容的类型。例如 anint
总是可以表示为 along
所以可以将它转换为 a long
。一些演员表有副作用。例如,float
如果将 a 强制转换为 a ,则会降低其精度int
。因此(int)1.5f
将导致 int 值 1。强制转换通常是更改类型的最快方法,因为它是单个 IL 运算符。例如,代码:
public void CastExample()
{
int i = 7;
long l = (long)i;
}
通过运行 IL 代码执行转换:
conv.i8 //convert to 8-byte integer (a.k.a. Int64, a.k.a. long).
解析是一些函数,它接受一种类型并返回另一种类型。它是一个实际的代码函数,而不仅仅是一个 IL 运算符。这通常需要更长的时间来运行,因为它运行多行代码。
例如,这段代码:
public void ParseExample()
{
string s = "7";
long l = long.Parse(s);
}
运行 IL 代码:
call int64 [mscorlib]System.Int64::Parse(string)
换句话说,它调用了一个实际的方法。在内部,Int64 类型提供了该方法:
public static long Parse(String s) {
return Number.ParseInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
和 Number.Parse:
[System.Security.SecuritySafeCritical] // auto-generated
internal unsafe static Int64 ParseInt64(String value, NumberStyles options, NumberFormatInfo numfmt) {
Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
NumberBuffer number = new NumberBuffer(numberBufferBytes);
Int64 i = 0;
StringToNumber(value, options, ref number, numfmt, false);
if ((options & NumberStyles.AllowHexSpecifier) != 0) {
if (!HexNumberToInt64(ref number, ref i)) {
throw new OverflowException(Environment.GetResourceString("Overflow_Int64"));
}
}
else {
if (!NumberToInt64(ref number, ref i)) {
throw new OverflowException(Environment.GetResourceString("Overflow_Int64"));
}
}
return i;
}
等等......所以你可以看到它实际上是在做很多代码。
现在事情变得更复杂的是,尽管强制转换通常是最快的,但类可以覆盖隐式和显式强制转换运算符。例如,如果我编写课程:
public class CastableClass
{
public int IntValue { get; set; }
public static explicit operator int(CastableClass castable)
{
return castable.IntValue;
}
}
我已经覆盖了显式转换运算符 for int
,所以我现在可以这样做:
public void OverridedCastExample()
{
CastableClass cc = new CastableClass {IntValue = 7};
int i = (int)cc;
}
这看起来像一个普通的演员表,但实际上它调用了我在课堂上定义的方法。IL代码是:
call int32 UnitTestProject1.CastableClass::op_Explicit(class UnitTestProject1.CastableClass)
所以无论如何,你通常想尽可能地投射。然后解析,如果你不能。