声明语句声明新的局部变量、局部常量或 reference 局部变量。若要声明局部变量,请指定其类型并提供其名称。可以在一个语句中声明多个相同类型的变量,如以下示例所示:

string zfc问候语;
int a , b , c;
List < double > lb;

在声明语句中,还可以使用变量的初始值对该变量进行初始化:

string zfc问候语 = "Hello";
int a = 3 , b = 2 , c = a + b;
List<double> lb = new ( );

前面的示例显式指定了变量的类型。还可以让编译器从其初始化表达式推断出变量的类型。为此,请使用 var 关键字而不是类型的名称。

若要声明局部常量,请使用 const 关键字,如以下示例所示:

const string zfc问候语 = "Hello";
const double 下限 = -10.0 , 上限 = -MinLimit;

隐式类型的局部变量

声明局部变量时,可以让编译器从初始化表达式推断出变量的类型。为此,请使用 var 关键字而不是类型的名称:

var WHY = "Hello";
Console . WriteLine ( WHY . GetType ( ) ); // System . String

var a = 32;
Console . WriteLine ( a . GetType ( ) ); // System . Int32

var LB = new List < double > ( );
Console . WriteLine ( LB . GetType ( ) ); // System . Collections . Generic . List`1 [ System . Double ]

如前面的示例所示,隐式类型的局部变量已强类型化。

备注:在已启用的可为 null 的感知上下文中使用 var,且初始化表达式的类型为引用类型时,即使初始化表达式的类型不可为 null,编译器也始终推断出可为 null 的引用类型。

var 的常见用途是用于构造函数调用表达式。使用 var 则不能在变量声明和对象实例化中重复类型名称,如下面的示例所示:
var LBint = new List < int > ( );
可以使用由目标确定类型的 new 表达式作为替代方法:

List < int > xs = new ( );
List < int >? ys = new ( );

使用匿名类型时,必须使用隐式类型的局部变量。以下示例显示了一个查询表达式,该表达式使用匿名类型保存我的虚拟妹妹的姓名和电话号码:

public class JieMei
    {
        private string _Name , _ChSh , _DH;

        public JieMei ( string 姓名 , string 城市 )
            {
                _Name = 姓名;
                _ChSh = 城市;
                _DH = "未知";
            }

        public JieMei ( string 姓名 , string 城市 , string 电话号码 )
            {
                _Name = 姓名;
                _ChSh = 城市;
                _DH = 电话号码;
            }

        public JieMei ( string 姓名 )
            {
                _Name = 姓名;
                _ChSh = "淄博市";
                _DH = "未知";
            }

        public string 姓名 => _Name;
        public string 城市
            {
                get { return _ChSh; }
                set { _ChSh = value; }
            }

        public string 电话号码
            {
                get { return _DH; }
                set { _DH = value; }
            }
    }

static void Main ( string [ ] args )
    {
        JieMei [ ] MeiMeis = [ new ( "张晓琳" , "济南市") , new ( "吴晓燕" , "淄博市" , "1234567") , new ( "程东红" , "淄博市" , "1234568") , new ( "何琳清" , "青岛市" , "23456789") , new ( "周楚红" ) ];
        var ZBMMs =
                    from JieMei in MeiMeis
                    where JieMei . 城市 == "淄博市"
                    select new
                        {
                            JieMei .姓名 ,
                            JieMei .电话号码
                         };
    foreach ( var Mei in ZBMMs )
        {
            Console.WriteLine ( $"姓名:{Mei . 姓名},电话号码:{Mei . 电话号码}" );
        }
    }

在前面的示例中,无法显式指定 ZBMMs 变量的类型。 类型为 IEnumerable < T >,但在本例中 T 为匿名类型,无法提供其名称。这就是需要使用 var 的原因。出于同一原因,在 foreach 语句中声明 customer 迭代变量时必须使用 var。

在模式匹配中,在 var 模式中使用 var 关键字。

Reference 变量

声明局部变量并在变量类型之前添加 ref 关键字时,声明 reference 变量,或 ref 局部变量:
ref int YYBL = ref 变量名;
reference 变量是引用另一个变量(称为引用)的变量。也就是说,reference 变量是其引用的别名。向 reference 变量赋值时,该值将分配给引用。读取 reference 变量的值时,将返回引用的值。以下示例演示了该行为:

int a = 1;
ref int YYa = ref a;
Console . WriteLine ( $"(a , YYa) 是:( {a} , {YYa} )" ); // 输出:( 1 , 1 )

a = 2;
Console . WriteLine ( $"(a , YYa) 是:( {a} , {YYa} )" ); // 输出:( 2 , 2 )

YYa = 20;
Console . WriteLine ( $"(a , YYa) 是:( {a} , {YYa} )" ); // 输出:( 20 , 20 )

使用 ref 赋值运算符 = ref 更改 reference 变量的引用,如以下示例所示:

void FF显示 ( int [ ] 整数集合 ) => Console . WriteLine ( string . Join ( "  " , 整数集合 ) );
int [ ] Zhss = [ 0 , 0 , 0 ];
FF显示 ( Zhss );

ref int YS = ref Zhss [ 0 ];
YS = 1;
FF显示 ( Zhss );

YS = ref Zhss [ ^ 1 ];
YS = 3;
FF显示 ( Zhss );

在前面的示例中,YS reference 变量初始化为第一个数组元素的别名。然后,ref 将被重新分配,以引用最后一个数组元素。

可以定义 ref readonly 局部变量。不能为 ref readonly 变量赋值。但是,可以 ref 重新分配这样的 reference 变量,如以下示例所示:

int [ ] Zhss = [ 1 , 2 , 3 ];
ref readonly int YS = ref Zhss [ 0 ];
// YS = 100; // 警告 CS0131:赋值号左边必须是变量、属性或索引器
Console . WriteLine ( YS ); // 输出:1
YS = ref Zhss [ ^ 1 ];
Console . WriteLine ( YS ); // 输出:3

可以将 ref 返回的值分配给引用变量,如下例所示:

static void Main ( string [ ] args )
    {
        Lei数据存储器 Zhss = new ( );
        Console . WriteLine ( $"原始数据:{Zhss}" );

        ref int ZD = ref Zhss . FF获取最大引用 ( );
        ZD = 0;
        Console . WriteLine ( $"更新后的数据:{Zhss}" );
    }

public class Lei数据存储器
    {
        private readonly int [  ] Zhss = [ 1 , 30 , 7 , 1557 , 381 , 63 , 1027 , 2550 , 511 , 1023 ];

        public ref int FF获取最大引用 ( )
            {
                ref int ZD = ref Zhss [ 0 ];
                for ( int i = 1 ; i < Zhss . Length ; i++ )
                    {
                        if ( Zhss [ i ] > ZD )
                            {
                                ZD = ref Zhss [ i ];
                            }
                    }
                return ref ZD;
        }

        public override string ToString ( )
            {
                return string . Join ( "  ", Zhss );
            }
   }

在前面的示例中,FF获取最大引用方法指的是 returns-by-ref 方法。它不返回最大值本身,而是引用返回,该引用返回是包含最大值的数组元素的别名。Run 方法将引用返回分配给 ZD reference 变量。然后,通过分配给 ZD,它会更新 store 实例的内部存储。还可以定义 ref readonly 方法。ref readonly 方法的调用方无法为其引用返回赋值。

foreach 语句的迭代变量可以是引用变量。

在性能关键型方案中,使用 reference 变量和返回可能会避免成本高昂的复制操作,从而提高性能。

编译器确保 reference 变量在时间上不超过其引用,并在其整个生存期内保持有效。

scoped ref

上下文关键字 scoped 限制值的生存期。scoped 修饰符将 ref-safe-to-escape 或 safe-to-escape 生存期分别限制为当前方法。实际上,添加 scoped 修饰符可确保代码不会延长变量的生存期。

可以将 scoped 应用于参数或局部变量。当类型为 ref struct 时,scoped 修饰符可以应用于参数和局部变量。否则,scoped 修饰符只能应用于局部 reference 变量。这包括使用 ref 修饰符声明的局部变量以及使用 in、ref 或 out 修饰符声明的参数。

当类型为 ref struct 时,使用 struct、out 参数和 ref 参数声明的方法将 scoped 修饰符隐式添加到 this。


兔子码农
4 声望1 粉丝

一个酒晕子