“C++ void Pointer”和“C# var”之间的区别

本文关键字:之间 区别 var C++ void Pointer | 更新日期: 2023-09-27 18:35:45

在学习C#时,我想到了这个问题。voidvar有什么区别?以下是我想分享的两个例子:

void * voidInt = (void *) 7;
void * voidChar = (void *) 'F';
void * voidCharArray = (void *) "AbcString";

这是var的例子:

var varInt = 7;
var varChar = 'F';
var varCharArray = "AbcString";
  • void是匿名数据类型吗?
  • 如果是,那么主要是什么varvoid的区别?

有人可以帮助我清除这种情况吗?

“C++ void Pointer”和“C# var”之间的区别

这里的其他答案非常好,但我认为它们没有清楚地了解基本原理。这是您感到困惑的基本原理,所以让我们解决这些问题。

  • 变量是包含存储位置
  • 变量类型相关联。
  • 局部变量有一个名称

所以voidIntvoidCharvoidCharArrayvarIntvarCharvarCharArray都是变量,它们都有与之关联的类型。可以为每个变量分配该类型的值或生成该类型的值,具体取决于变量是写入还是读取。

好的,那么现在什么是指针?

  • 类型具有相应的指针类型。(请注意,在不安全的 C# 中,只有非托管类型具有相应的指针类型。
  • void *类型是一种特殊的指针类型。
  • 指针是一个值。
  • 可以取消引用 T* 类型的指针以生成 T 类型的变量T*一定不能void*.
  • 指针可以显式转换为任何整型类型或从任何整型转换,尽管这些操作允许丢失信息并依赖于实现细节。
  • 任何指针值都可以隐式转换为 void*
  • 任何void*值都可以显式转换为任何指针类型值。

C#中的var是什么?

  • var是一种"语法糖",它告诉编译器从初始化器推断变量的类型,而不是要求将其写出来。

C#中的"匿名类型"是什么?

  • C# 中的某些表达式具有未声明且没有名称的类型;这些类型称为"匿名"类型。

所以现在我们可以看看你的程序,看看每行做什么。

void * voidInt = (void *) 7;

voidInt 是类型 void* 的变量。分配给它的值是将整数 7 转换为指针,这几乎可以肯定是任何现代操作系统上的垃圾指针。 这段代码本质上是荒谬的。

更明智的代码是:

int myInt = 7;
int* intPtr = &myInt;
void* voidInt = intPtr;

这意味着myInt是一个保存值7的变量,intPtr是一个保存指针的变量;当该指针被取消引用时,它会产生变量myIntvoidInt 是一个保存任何指针的变量,从intPtr读取的值是一个指针。所以现在voidIntintPtr都持有指向变量myInt的指针。

void * voidChar = (void *) 'F';

这里也是一样。字符F被视为数字并转换为存储在变量中的指针值。这是不明智的。合理的代码是这样的:

char myChar = 'F';
void *voidChar = &myChar;

但这完全有道理:

void * voidCharArray = (void *) "AbcString";

C++ 中的字符串文本可转换为 char*,该是指向第一个字符的存储的指针,并且该指针可转换为 void*

这个呢?

var varInt = 7;
var varChar = 'F';
var varCharArray = "AbcString";

这只是一种愉快的写作方式

int varInt = 7;
char varChar = 'F';
string varCharArray = "AbcString";
每个变量

都有其给定的类型,每个赋值在变量中存储该类型的值。

匿名类型呢?

var anon = new { X = 123, Y = 456 };

这将生成一个匿名类型的变量,其中匿名类型具有两个属性 X 和 Y,均为 int 类型。类型没有名称,因此无法在声明中写出类型,因此必须使用var

这里的关键是确保您掌握了基础知识:指针是,它们可能会被取消引用,这样做会产生一个变量。由于指针是,因此它们本身可以存储在指针类型的变量中。这几乎与var无关,这是C#中一种令人愉快的方式,可以让编译器完成确定变量应该具有什么类型的工作。

voidvar实际上没有任何共同点:

  • void(由 C 和 C++ 中的指针变量使用)表示未指定(不是确定)类型。 在托管 C# 中不允许使用void**(尽管非常弱的类型(如object引用)可能是近似值)。通常,void*类型需要重新转换才能有用。

  • 但是void方法/函数的返回类型意味着相同在两种语言中,这是为了传达没有返回值(如 Scala 中的Unit

  • 相比之下,C# 中的var定义了一个隐式类型变量 - 该变量仍然具有强类型,但在编译时从右侧推断实际类型。

例如

var v1 = "Foo"; // v1 is a string, because it is inferred from the right hand side
var v2 = XDocument.Parse(@"c:'temp'foo.xml"); // v2 is the return type of the function

使用匿名类型时通常需要var - 这可能是您在var和匿名类型之间建立连接的地方:

var v3 = new { Name = "Foo", Value = 123};  // v3 is strongly typed, anonymous class.

var 对于将变量分配给 LINQ 表达式的返回值特别有用,其中的类型可能非常复杂:

var v3 = db.Persons
      .Join(db.Cities, p => p.CityId, c => c.Id, (p, c) => new {Person = p, City = c})
      .GroupBy(pc => pc.City.Name);
*

实际上,这并不完全正确,您可以在 C# 中使用 void* 与不安全

编辑

还有一件事值得一提,从 C#6 开始,隐式var类型只能用于局部变量,即 C# 不支持方法返回类型的隐式类型(与 Scala 等函数式语言不同,在大多数情况下,编译器也可以推断方法的返回类型)。

  • 在不安全的上下文中,相当于 C# 中的 C++ void*void* 。可以将任何数据指针类型分配给void*
  • 在安全的上下文中,object(松散地)是相应的概念。任何类/接口/结构实例都可以分配给它。
  • C++ 中 C# var的等效项是 auto 。当用于声明和初始化局部变量时,它充当分配给该变量的表达式的类型(如果可能)。

你可以用 c++ void 指针来做到这一点:

void * val = (void *) 7;
val = (void *) "Abcd";

但是你不能用 c# var 做到这一点:

var val = 7;
val = "abcd";

这将引发错误。

更新

如果要实现类似的void *行为,可以使用dynamic

dynamic val = (dynamic) 7;
val = (dynamic) "ABC";

使用 var 时,变量的实际类型在编译时确定。但是,当使用dynamic时,变量的实际类型是在运行时确定的。