Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C中引用类型的内存显式强制转换解释#_C#_C++_C_Casting_Reference - Fatal编程技术网

C# C中引用类型的内存显式强制转换解释#

C# C中引用类型的内存显式强制转换解释#,c#,c++,c,casting,reference,C#,C++,C,Casting,Reference,在MSDN中,“对于引用类型,如果需要从基类型转换为派生类型,则需要显式强制转换” 在wiki中,“在编程语言理论中,引用类型是指内存中对象的数据类型。另一方面,指针类型指内存地址。引用类型可以被认为是隐式取消引用的指针。”这是C中的情况 在C#?中考虑引用类型的显式强制转换时,如何解释内存存储过程对于大多数情况,引用变量和指针变量之间实际上没有什么可以想象的区别。两者都指向内存中的一个位置。引用(或指针)变量的类型告诉编译器可以使用它执行哪些操作 >代替C(主要用于基本类型(如int或字节)

在MSDN中,“对于引用类型,如果需要从基类型转换为派生类型,则需要显式强制转换”

在wiki中,“在编程语言理论中,引用类型是指内存中对象的数据类型。另一方面,指针类型指内存地址。引用类型可以被认为是隐式取消引用的指针。”这是C中的情况


在C#?

中考虑引用类型的显式强制转换时,如何解释内存存储过程对于大多数情况,引用变量和指针变量之间实际上没有什么可以想象的区别。两者都指向内存中的一个位置。引用(或指针)变量的类型告诉编译器可以使用它执行哪些操作

<> >代替C(主要用于基本类型(如int或字节)的指针),首先考虑C++对象指针。这实际上与C#中的几乎相同:

MyBaseClass*a=新的MyBaseClass();
a->BaseMethod();//使用->运算符调用方法(取消引用和调用)
MyBaseClass*b=新的MyDerivedClass();
b->DerivedMethod();//错误:MyBaseClass没有这样的方法
//正确的C++风格的铸造。
MyDerivedClass*c=动态投影(b);
//上述快捷方式不进行型式试验。
//MyDerivedClass*c=(MyDerivedClass*)b;
c->DerivedMethod();//好啊
这几乎将1:1转换为C#,因此引用类型(从程序员的角度来看)只是具有定义类型的指针。唯一的明显区别是C语言中的直接C样式的转换相当于C++中的Tyype强制转换,这将确保永远不能向引用变量分配错误的目标实例。p> 因此,引用类型和指向对象的指针之间的区别是(C#是托管语言这一事实暗示了其中的大部分区别):

  • 引用变量永远不能指向无效内存(NULL除外)
  • 引用变量永远不能指向非其类型的对象
  • 为引用变量赋值时,始终测试类型
  • 引用变量上的强制转换需要检查目标对象是否为给定类型
在大多数情况下,引用变量和指针变量之间并没有太大的差别。两者都指向内存中的一个位置。引用(或指针)变量的类型告诉编译器可以使用它执行哪些操作

<> >代替C(主要用于基本类型(如int或字节)的指针),首先考虑C++对象指针。这实际上与C#中的几乎相同:

MyBaseClass*a=新的MyBaseClass();
a->BaseMethod();//使用->运算符调用方法(取消引用和调用)
MyBaseClass*b=新的MyDerivedClass();
b->DerivedMethod();//错误:MyBaseClass没有这样的方法
//正确的C++风格的铸造。
MyDerivedClass*c=动态投影(b);
//上述快捷方式不进行型式试验。
//MyDerivedClass*c=(MyDerivedClass*)b;
c->DerivedMethod();//好啊
这几乎将1:1转换为C#,因此引用类型(从程序员的角度来看)只是具有定义类型的指针。唯一的明显区别是C语言中的直接C样式的转换相当于C++中的Tyype强制转换,这将确保永远不能向引用变量分配错误的目标实例。p> 因此,引用类型和指向对象的指针之间的区别是(C#是托管语言这一事实暗示了其中的大部分区别):

  • 引用变量永远不能指向无效内存(NULL除外)
  • 引用变量永远不能指向非其类型的对象
  • 为引用变量赋值时,始终测试类型
  • 引用变量上的强制转换需要检查目标对象是否为给定类型
引用对象存储在堆上,可以从代码中引用它们。堆上的对象是给定类型的

从代码中,您可以创建对它的引用,并且这些引用可以转换为其他类型

现在,有两个案例,在参考文章中进行了描述。我将使用其中的示例使其更简单

1。隐式转换

当您在代码中没有特别要求隐式转换时,就会发生隐式转换。编译器必须自己知道如何做到这一点

1.1。值类型

如果您试图转换的值的类型是大小,这允许您将其存储在内存大小中,使您希望转换为的类型的大小变大,那么编译器将允许您这样做。这主要是针对数值的,因此请参考参考文章中的示例:

// Implicit conversion. num long can
// hold any value an int can hold, and more!
int num = 2147483647;
long bigNum = num;
所以,由于int比long“小”,编译器将允许您这样做

1.2。参考类型

假设您有以下类定义:

class Base {    

}

class Derived : Base {
    public int IntProperty { get; set; }
    public int CalculateSomething ()
    {
         return IntProperty * 23;
    }
}
然后您可以安全地进行如下转换:

Derived d = new Derived();
Base b = d;
这是因为您在堆上创建的对象d的类型是
派生的
,并且由于它是从类型
派生的类型,因此它保证拥有所有
拥有的成员。因此,转换引用并将
派生的
对象用作
基础
对象是安全的。因为派生的是Base
派生的:Base

2。显式转换

假设我们的项目中有另一个类:

class DerivedLike
{
    public int IntProp { get; set; }
    public int CalculateSomethingElse()
    {
        return IntProp * 23;
    }
}
如果我们写

DerivedLike dl = new DerivedLike();
Derived d = dl;
我们将从编译器得到,它不能隐式地将类型
DerivedLike
转换为
Derived

这是因为这两种引用类型完全不同,所以编译器不允许您这样做。这些类型具有不同的属性和方法

DerivedLike dl = new DerivedLike();
Derived d = dl;
class DerivedLike
{
    public static explicit operator Derived(DerivedLike a)
    {
        return new Derived() { IntProperty = a.IntProp};
    }
    public int IntProp { get; set; }
    public int CalculateSomethingElse()
    {
        return IntProp * 23;
    }
}
DerivedLike dl = new DerivedLike();
Derived d = (Derived)dl;
DerivedLike dl = new DerivedLike();
Derived d = (Derived)dl;