C# 如何创建变量(非类成员)“;只读;在C中#

C# 如何创建变量(非类成员)“;只读;在C中#,c#,c#-3.0,c#-4.0,C#,C# 3.0,C# 4.0,我是C世界的新手,在C中找不到声明只读变量的方法(类似于在C++中声明“const”变量)。有吗 我给你举个例子: ... int f() { return x; } // x is not const member ... void g() { int readOnlyVar = f(); // is there a method to declare readOnlyVar as read only or const // Some code in which I want

我是C世界的新手,在C中找不到声明只读变量的方法(类似于在C++中声明“const”变量)。有吗

我给你举个例子:

...
int f() { return x; } // x is not const member
...
void g() {
    int readOnlyVar = f(); // is there a method to declare readOnlyVar as read only or const

    // Some code in which I want to restrict access to readOnlyVar to read only 
}

没有完全相同的类比

readonly
关键字允许对变量值进行变异,但只能在构造函数中进行变异

const
关键字意味着该值不能变化,必须是编译时常量,并且只能是以下类型之一:sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal、bool、string、枚举类型或引用类型。(C#4.0规范§10.4)


在c#中,
只读
仅适用于字段,不能应用于局部变量。

否,您的代码示例没有解决方案

C#中的
const
用于编译时常量,由于变量的值来自函数,因此编译时不知道它的值

readonly
关键字与您要查找的内容类似,但这仅适用于类中的成员变量(并且只允许在类的构造函数中设置变量)

但是,另一方面,你为什么需要它呢?如果您的函数很长,则应将其重构为较小的函数。如果不是很长,那么你为什么需要执行这样的规则?请不要指定给
readOnlyVar
恐怕是我给您的最好建议。

在c#中,我们使用const或readonly关键字来声明常量

常数

常量成员是在编译时定义的,不能在运行时更改。常量使用const关键字声明为字段,并且必须在声明时初始化。比如,

public class MyClass
{
  public const double PI = 3.14159;
}
PI不能在应用程序中代码中的任何其他地方更改,因为这将导致编译器错误

只读

只读成员类似于常量,因为它表示不变的值。区别在于只读成员可以在运行时在构造函数中初始化,也可以在声明时初始化。例如:

public class MyClass
{
  public readonly double PI = 3.14159;
}   

由于只读字段可以在声明或构造函数中初始化,因此根据使用的构造函数,只读字段可以具有不同的值。只读字段也可用于运行时常量,如以下示例所示:

public static readonly uint l1 = (uint)DateTime.Now.Ticks;
注释

只读成员不是隐式静态的,因此,如果需要,可以将static关键字显式应用于只读字段

只读成员可以通过在初始化时使用new关键字来保存复杂对象。 只读成员不能保存枚举

这里值得赞扬:
将变量设置为只读有两种方法

public class ClassA
{
  private const int I = 5;
  private readonly int J = 5;
}

const关键字将在编译时设置该值。readonly关键字将在构造时设置值。因此,如果每个实例需要不同的值,请使用readonly。否则使用常量

这不是语言功能,而是。不过,你确实有一些选择。您可以将方法的实现替换为具有
readonly
成员变量的类。然而,这是一个巨大的痛苦,并且确实会使代码的大小爆炸。(当您编写lambda或使用
async
方法时,C#会执行类似于将局部变量提升到类字段的操作,并将lambda或async方法转换为自动生成类上的方法。我们基本上也在执行相同的操作,但需要手动设置
readonly

另一种需要更少代码但仍然笨重的替代方法是滥用foreach的
功能。
foreach
关键字不允许您分配给迭代变量。所以你可以这样做:

class Scope
{
    int x;

    int f() => x;

    void g()
    {
        foreach (var readOnlyVar in new[] { f(), })
        {
            // Some code in which I want to restrict access to readOnlyVar to read only 

            // error CS1656: Cannot assign to 'readOnlyVar' because it is a 'foreach iteration variable'
            readOnlyVar = 3;
        }
    }
}

foreach
方法使匿名类型的使用更加容易,但是您可以使用泛型结合类型推断来使用匿名类型和类方法。

提到
const
不能像我预期的那样完全应用于每种数据类型,只是想确定一下,谢谢!都德,我认为遵循
参考透明度
准则就足够了,你的
方法必须尽可能小
,你可以一眼就知道应该做什么。
class Scope
{
    int x;

    int f() => x; // x is not const member

    void g()
    {
        new gImpl(f()).Run();
    }

    class gImpl
    {
        readonly int readOnlyVar;
        public gImpl(
            int readOnlyVar)
        {
            this.readOnlyVar = readOnlyVar;
        }
        public void Run()
        {
            // Some code in which I want to restrict access to readOnlyVar to read only 

            // error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
            readOnlyVar = 3;
        }
    }
}
class Scope
{
    int x;

    int f() => x;

    void g()
    {
        foreach (var readOnlyVar in new[] { f(), })
        {
            // Some code in which I want to restrict access to readOnlyVar to read only 

            // error CS1656: Cannot assign to 'readOnlyVar' because it is a 'foreach iteration variable'
            readOnlyVar = 3;
        }
    }
}