C#等效于C 中的const指针

C# equivalent of a const pointer/pointer to const in C++

本文关键字:中的 const 指针      更新时间:2023-10-16

我正在学习C 的基础知识,来自.net world(c#)。

我发现有趣的一个主题是 const 关键字及其用指针的用法(const指针/指针到const)。

我想知道C 具有的const指针/指针的C#语言是否等效?(我知道C#没有指针,我正在考虑参考为C#中的指针类型)。

同样,出于兴趣,如果没有这样的同等学历,那么不包括这样的功能的决定是什么?

在c#中没有直接等同于将引用作为'const'的直接等效,但是还有其他方法可以实现其目的。这样做的最常见方法是使您的参考类要么完全不变(一旦构建,其状态就永远不会改变),要么将其作为不可变的公共接口传递。后者是最接近" const"参数合同的意图(我会给您一些内容,以便您可以使用它,但是我要求您不要更改它。)一个行为不善的客户可以'当然,将公共界面抛弃为一种可变形式,但这仍然使意图清晰。您也可以在C 中"抛弃" const,认为这很少是一个好主意。


C 中的另一件事是,当您知道您所传递的参考文献的寿命受到范围的限制时,您通常会宁愿像const一样通过。C 通常遵循方法范围内在堆栈中创建和破坏对象的模式,因此对这些对象的任何引用均不应在该范围之外持续存在(因为在范围掉落后使用它们可能会导致真正令人讨厌的堆栈腐败崩溃。)const引用不应突变,因此有很大的暗示,即以后将其存储在某个地方是个坏主意。一种具有const参数的方法是可以安全地传递这些范围的参考文献。由于c#永远不允许将引用对堆栈上的对象(在参数之外)上,因此这不是一个问题。

c#(或java)中常数对象的概念(即 readonly)的概念大约对应于C 中的object *const,即对非恒定对象的常数指针。

有几个原因 - 对于正确指定const并在语言中有用的人很难。以C 为例,您必须两次定义许多方法,仅对签名进行了小更改,const_cast,const仅应用浅的事实,等等。

因此,C#获得了简单的解决方案,以使语言变得更简单-D以传递的const正确性等方向使用。据我所知(从未在D中写下一行,所以请用一粒盐来做)。

C#/Java中通常的解决方案是拥有不变的类,可能使用构建器模式或禁止变化的简单包装器(例如,所有无法解码的集合包含其他集合并为突变方法提供了类似的突变方法)。

8,000,000年后,但是C#7.2使用" in"关键字,就像const一样。它告诉编译器通过参考(例如参考或输出)传递结构或原始变量,但该方法不会修改变量。

public void DoSomething(in int variable){
    //Whatever
}

在功能上等效于C 'S

void Foo::DoSomething(int& const  variable){
    //Whatever
}

或甚至可以说

void Foo::DoSomething(int const * const variable){
    //Whatever
}
根据MSDN的说法,

在C#中这样做的主要原因是告诉编译器可以通过参考传递变量,因为它不会被修改。通过大型结构

,这可能会取得更好的性能

关于恒定指针,请参阅此答案:const之间的差异。指针和参考?

换句话说,C 中的参考与大多数应用程序的const指针非常相似。但是,C#中的引用更接近C 的指针。

参考对象以参数为c#中的方法可以重新定义(例如,从对象实例a到对象实例b),但是b的寿命仅在方法范围内,并且一旦返回呼叫者就被处置了(因为指针本身是按值传递的),呼叫者的引用始终是A。从这个意义上讲,您可以在C#中自由传递参考文献,并且知道它们不能指向不同的对象(除非使用Ref/Out关键字)。

c#示例 -

class Foo
{
    //Stateful field
    public int x;
    //Constructor
    public Foo()
    {
        x = 6;  
    }
}
public class Program
{
    public static void Main()
    {
        var foo = new Foo();
        foo.x = 8;
        VarTestField(foo);      
        Console.WriteLine(foo.x);
        RefTestField(ref foo);
        Console.WriteLine(foo.x);       
    }   
    //Object passed by reference, pointer passed by value
    static void VarTestField(Foo whatever){
        whatever = new Foo();
    }
    //Object passed by reference, pointer passed by reference
    static void RefTestField(ref Foo whatever){
        whatever = new Foo();
    }
}

输出:

8

6

所以不,您无法在C#中声明一个恒定的指针。尽管如此,使用经过验证的设计模式,算法和OOP基础知识,以及语言的内置语法,您可以实现所需的行为。