C# 施压和强迫有什么区别?
我已经看到这两个术语在各种在线解释中几乎可以互换使用,我查阅的大多数教科书也不完全清楚它们之间的区别 有没有一种简单明了的方式来解释你们所知道的差异 类型转换(有时也称为类型转换) 在需要另一种类型的上下文中使用一种类型的值 非旋转类型转换(有时称为类型双关语) 不改变底层位的一种更改 胁迫 当周围上下文需要第二种类型的值时,编译器自动将一种类型的值转换为另一种类型的值的过程C# 施压和强迫有什么区别?,c#,oop,C#,Oop,我已经看到这两个术语在各种在线解释中几乎可以互换使用,我查阅的大多数教科书也不完全清楚它们之间的区别 有没有一种简单明了的方式来解释你们所知道的差异 类型转换(有时也称为类型转换) 在需要另一种类型的上下文中使用一种类型的值 非旋转类型转换(有时称为类型双关语) 不改变底层位的一种更改 胁迫 当周围上下文需要第二种类型的值时,编译器自动将一种类型的值转换为另一种类型的值的过程 强制转换是将一个对象类型视为另一个类型的过程,强制转换是将一个对象转换为另一个对象 请注意,在前一个过程中,不涉及转换,
强制转换是将一个对象类型视为另一个类型的过程,强制转换是将一个对象转换为另一个对象 请注意,在前一个过程中,不涉及转换,您有一个类型希望将其视为另一个类型,例如,您有3个不同的对象继承自一个基类型,并且您有一个方法,如果您知道特定的子类型,则在任何时候都将采用该基类型,您可以将其强制转换为它是什么,并使用该对象的所有特定方法和属性,而这不会创建该对象的新实例 另一方面,强制意味着在新类型的内存中创建一个新对象,然后将原始类型复制到新类型,将两个对象都保留在内存中(直到垃圾收集器拿走其中一个或两个) 作为例子,考虑下面的代码:
class baseClass {}
class childClass : baseClass {}
class otherClass {}
public void doSomethingWithBase(baseClass item) {}
public void mainMethod()
{
var obj1 = new baseClass();
var obj2 = new childClass();
var obj3 = new otherClass();
doSomethingWithBase(obj1); //not a problem, obj1 is already of type baseClass
doSomethingWithBase(obj2); //not a problem, obj2 is implicitly casted to baseClass
doSomethingWithBase(obj3); //won't compile without additional code
}
- obj1在没有任何强制转换或强制(转换)的情况下被传递,因为它已经是相同类型的
baseClass
- obj2隐式地强制转换为base,这意味着不会创建新对象,因为obj2已经可以是
baseClass
- obj3需要以某种方式转换为base,您需要提供自己的方法从
转换为otherClass
,这将涉及创建一个类型为baseClass的新对象,并通过从obj3复制数据来填充它baseClass
以下是几个例子(摘自: 强制(隐式):
double d;
int i;
if (d > i) d = i;
double da = 3.3;
double db = 3.3;
double dc = 3.4;
int result = (int)da + (int)db + (int)dc; //result == 9
强制转换(显式):
double d;
int i;
if (d > i) d = i;
double da = 3.3;
double db = 3.3;
double dc = 3.4;
int result = (int)da + (int)db + (int)dc; //result == 9
以下是来自以下网站的帖子: 强制铸造和铸造之间的区别常常被忽略。我明白为什么;对于这两种操作,许多语言具有相同(或相似)的语法和术语。有些语言甚至可能将任何转换称为“转换”,但下面的解释涉及CTS中的概念 如果试图将某个类型的值指定给其他类型的位置,则可以生成与原始类型具有类似含义的新类型的值。这是强迫。强制允许您通过创建在某种程度上类似于原始类型的新值来使用新类型。某些强制可能会丢弃数据(例如,将整数0x12345678转换为短0x5678),而其他强制可能不会丢弃数据(例如,将整数0x00000008转换为短0x0008或长0x0000000000000008) 回想一下,值可以有多种类型。如果您的情况稍有不同,并且您只想选择一种不同的值类型,则铸造是作业的工具。强制转换只是表示希望对值包含的特定类型进行操作 代码级别的差异从C#到IL不等。在C#中,施法和强制看起来非常相似:
static void ChangeTypes(int number, System.IO.Stream stream)
{
long longNumber = number;
short shortNumber = (short)number;
IDisposable disposableStream = stream;
System.IO.FileStream fileStream = (System.IO.FileStream)stream;
}
在白细胞介素水平上,它们是完全不同的:
ldarg.0
conv.i8
stloc.0
ldarg.0
conv.i2
stloc.1
ldarg.1
stloc.2
ldarg.1
castclass [mscorlib]System.IO.FileStream
stloc.3
至于逻辑层面,有一些重要的区别。最重要的是要记住强制创造了一个新的价值,而施法却没有。原始值和铸造后的值的标识相同,而强制值的标识不同于原始值;协同创建一个新的、不同的实例,而强制转换不创建。一个推论是,施法的结果和原作总是相等的(在同一性和平等性上),但强制值可能等于或不等于原作,并且从不共享原作的同一性
在上面的示例中很容易看出强制的含义,因为数值类型总是按值复制的。使用引用类型时,事情会变得有点棘手
class Name : Tuple<string, string>
{
public Name(string first, string last)
: base(first, last)
{
}
public static implicit operator string[](Name name)
{
return new string[] { name.Item1, name.Item2 };
}
}
类名:元组
{
公共名称(第一个字符串,最后一个字符串)
:底座(第一个、最后一个)
{
}
公共静态隐式运算符字符串[](名称)
{
返回新字符串[]{name.Item1,name.Item2};
}
}
在下面的示例中,一个转换是强制转换,而另一个是强制转换
Tuple<string, string> tuple = name;
string[] strings = name;
Tuple Tuple=name;
字符串[]字符串=名称;
在这些转换之后,元组和名称是相等的,但是字符串不等于它们中的任何一个。通过在Name类上实现Equals()和operator==()来比较Name和string[],您可以使情况稍微好一点(或者稍微复杂一点)。这些操作符将“修复”比较问题,但您仍然有两个单独的实例;对字符串的任何修改都不会反映在名称或元组中,而对
object o = 1;
int i = (int)o;//Explicit conversions require a cast operator
i.GetType();//The type has been explicitly converted to System.Int32. Object type is not preserved. This meets the definition of Coercion not casting.
TYPE CASTING | TYPE COERCION
|
1. Explicit i.e., done by user | 1. Implicit i.e., done by the compiler
|
2. Types: | 2. Type:
Static (done at compile time) | Widening (conversion to higher data
| type)
Dynamic (done at run time) | Narrowing (conversion to lower data
| type)
|
3. Casting never changes the | 3. Coercion can result in representation
the actual type of object | as well as type change.
nor representation. |