"C++ void Pointer"和"C# var"的区别
Difference between "C++ void Pointer" and "C# var"
在学习C#时,我想到了这个问题。void
和var
有什么区别?以下是我想分享的两个例子:
void * voidInt = (void *) 7;
void * voidChar = (void *) 'F';
void * voidCharArray = (void *) "AbcString";
这是var
的例子:
var varInt = 7;
var varChar = 'F';
var varCharArray = "AbcString";
void
是匿名数据类型吗?- 如果是,那么主要是什么
var
和void
的区别?
有人可以帮助我清除这种情况吗?
这里的其他答案非常好,但我认为它们没有清楚地了解基本原理。这是您感到困惑的基本原理,所以让我们解决这些问题。
- 变量是包含值的存储位置。
- 变量与类型相关联。
- 局部变量有一个名称。
所以voidInt
、voidChar
、voidCharArray
、varInt
、varChar
和varCharArray
都是变量,它们都有与之关联的类型。可以为每个变量分配该类型的值或生成该类型的值,具体取决于变量是写入还是读取。
好的,那么现在什么是指针?
- 类型具有相应的指针类型。(请注意,在不安全的 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
是一个保存指针的变量;当该指针被取消引用时,它会产生变量myInt
。 voidInt
是一个保存任何指针的变量,从intPtr
读取的值是一个指针。所以现在voidInt
和intPtr
都持有指向变量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#中一种令人愉快的方式,可以让编译器完成确定变量应该具有什么类型的工作。
void
和var
实际上没有任何共同点:
-
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:tempfoo.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
时,变量的实际类型是在运行时确定的。
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- int(c) 和 c-'0' 之间的区别。C++
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- C++ - "!pointer"和"pointer == nullptr"的区别?
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 在 const 函数中通过引用和指针返回之间的区别
- 我想知道长双倍和双倍之间的区别
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- 返回递归调用和仅递归调用的区别
- Qt:remove() 和 rmdir() 有什么区别
- 这 4 个 lambda 表达式之间有什么区别?
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- (double) 和 double() 之间的区别
- ( var > x) 和 ( x < var)之间有什么区别吗?
- int *ptr = &var 和 int *ptr 之间的区别;*PTR = 和变量?
- "C++ void Pointer"和"C# var"的区别
- cout set_precision(5) + 固定和 printf( "%lf.5" ,var) 之间的区别