如果我在C#中转换对象,它是否仍然引用原始对象强制转换?
作为一个例子,如果我创建一个方法来更改一个对象然后根据调用的特定实现强制转换该对象,原始对象是否会被保留?
public bool CallChangeString()
{
String str = "hello";
ChangeObject(str);
return String.Equals("HELLO", str);
}
public void ChangeObject(Object obj)
{
String str = obj as String;
str.ToUpper(); // pretend for the sake of this that this changes str to upper case
}
在这种情况下,String.Equals会返回true还是false?
是否有任何情况会导致新对象无法保留它的引用?
答案 0 :(得分:8)
取决于你在做什么演员。您可以想到两个主要的投射组:
嗯,这不是很有帮助,这正是你所要求的。
什么演员不保留身份?所有那些需要在对象本身进行代表性更改的内容,即构成对象的位 更改。
实施例?值类型之间的所有转换:int
到long
,int
到double
等,任何装箱或拆箱转换等。组成{{1与构成long
的那些非常不同。
更多例子?任何用户定义的转换运算符,显式或隐式。为什么?因为编译器不允许用户定义的保留标识的强制转换,因为编译器已经为你做了这些:
int
请注意用户定义的强制转换的一般模式:
class Foo : IFoo
{
public static implicit operator object(Foo foo) => return foo; //Compile time error
public static implicit operator IFoo(Foo foo) => return foo; //compile time error.
public static explicit operator Bar(Foo foo) => return new Bar(foo);
}
潜伏
无论它返回什么地方。多数民众赞成,马上告诉你
cast无法保留身份...您正在返回一个新对象。那么,是什么身份保留演员表或转换?那些没有触摸对象的人; 参考转化。
咦?但等等,重点是我投射对象,怎么会这样?
在参考转化中,您仅"施放"指向对象的引用。对象总是一样的。当然,这只在参考类型中有意义,这就是为什么价值类型不具有保持身份转换的身份的原因;除非它们是盒装的,否则没有对值类型的引用。
实施例? new
至object
,string
至Foo
,IFoo
至Giraffe
等。
请注意,引用类型也可以很好地实现用户定义的转换,但这些不会保留标识。
所有这一切,这是拇指的规则:
Animal
是用户定义的强制转换,有人必须在类(long)2
中实现它)。因此,在回答您的问题时,System.Int64
是参考转化,这意味着var str = obj as string
是ReferenceEquals(str, obj)
; true
和str
指向完全相同的对象,唯一的区别是引用的类型。
答案 1 :(得分:3)
字符串是不可变的,因此您无法更改它们。但是,您可以创建新实例:
myString = myString.Replace("", ".");
请注意myString
是一个与原始字符串无关的全新实例。因此,即使您为myString
指定了不同的内容,这也不会影响依赖于原始实例的调用代码。
在您的示例中,str.ToUpper()
不会更改任何内容,因为ToUpper
会返回新字符串,而不是更改当前(str
)实例。
强制为同一个实例创建一个新的引用。因此,对实例的修改将反映在其所有引用中,无论是转换实例还是仅重新引用
var a = (MyType) myInstance;
a.MyProperty = 4;
在最后一个语句之后,a
和myInstance
都将属性MyProperty
设置为4
,因为变量a
和myInstance
都参考同一个MyType
。
答案 2 :(得分:-2)
像这样改变你的方法,看看结果)
public bool CallChangeString()
{
String str = "hello";
ChangeObject(str);
return String.Equals("HELLO", str);
}