C#的成员访问运算符和表达式

1.成员访问运算符和表达式

访问类型成员时,可以使用以下运算符和表达式:

2.成员访问表达式

可以使用 . 标记来访问命名空间或类型的成员,如以下示例所示:

  • 使用 . 访问命名空间内的嵌套命名空间,如以下 using directive 的示例所示:

C#复制

using System.Collections.Generic;
  • 使用 . 构成限定名称以访问命名空间中的类型,如下面的代码所示:
    System.Collections.Generic.IEnumerable<int> numbers = new int[] { 1, 2, 3 };

    使用 using 指令来使用可选的限定名称。

  • 使用 . 访问类型成员(静态和非静态),如下面的代码所示
    var constants = new List<double>();
    constants.Add(Math.PI);
    constants.Add(Math.E);
    Console.WriteLine($"{constants.Count} values to show:");
    Console.WriteLine(string.Join(", ", constants));
     还可以使用 . 访问扩展方法

3.索引器运算符 []

方括号 [] 通常用于数组、索引器或指针元素访问。

4.数组访问

下面的示例演示如何访问数组元素:

int[] fib = new int[10];
fib[0] = fib[1] = 1;
for (int i = 2; i < fib.Length; i++)
{
    fib[i] = fib[i - 1] + fib[i - 2];
}
Console.WriteLine(fib[fib.Length - 1]);  // output: 55

double[,] matrix = new double[2,2];
matrix[0,0] = 1.0;
matrix[0,1] = 2.0;
matrix[1,0] = matrix[1,1] = 3.0;
var determinant = matrix[0,0] * matrix[1,1] - matrix[1,0] * matrix[0,1];
Console.WriteLine(determinant);  // output: -3

如果数组索引超出数组相应维度的边界,将引发 IndexOutOfRangeException

如上述示例所示,在声明数组类型或实例化数组实例时,还会使用方括号。

5.索引器访问

下面的示例使用 .NET Dictionary<TKey,TValue> 类型来演示索引器访问:

var dict = new Dictionary<string, double>();
dict["one"] = 1;
dict["pi"] = Math.PI;
Console.WriteLine(dict["one"] + dict["pi"]);  // output: 4.14159265358979

 6.[]的其他用法

要了解指针元素访问,请参阅与指针相关的运算符一文的指针元素访问运算符 [] 部分。

方括号还用于指定属性

[System.Diagnostics.Conditional("DEBUG")]
void TraceMethod() {}

7. Null 条件运算符 ?. 和 ?[]

Null 条件运算符在 C# 6 及更高版本中可用,仅当操作数的计算结果为非 null 时,null 条件运算符才会将成员访问 ?. 或元素访问 ?[] 运算应用于其操作数;否则,将返回 null。 即:

  • 如果 a 的计算结果为 null,则 a?.x 或 a?[x] 的结果为 null

  • 如果 a 的计算结果为非 null,则 a?.x 或 a?[x] 的结果将分别与 a.x 或 a[x] 的结果相同。

8.NULL 条件运算符采用最小化求值策略。 也就是说,如果条件成员或元素访问运算链中的一个运算返回 null,则链的其余部分不会执行。 在以下示例中,如果 A 的计算结果为 null,则不会计算 B;如果 A 或 B 的计算结果为 null,则不会计算 C

A?.B?.Do(C);
A?.B?[C];

 

9.如果 A 可以为 NULL,但如果 A 不为 NULL,B 和 C 将不为 NULL,你只需要对 A 应用 NULL 条件运算符:

A?.B.C();

10.在上述示例中,如果 A 为 null,则不会计算 B,也不会调用 C()。 但是,如果链接的成员访问被中断,例如被 (A?.B).C() 中的括号中断,则不会发生短路。

以下示例演示了 ?. 和 ?[] 运算符的用法:

double SumNumbers(List<double[]> setsOfNumbers, int indexOfSetToSum)
{
    return setsOfNumbers?[indexOfSetToSum]?.Sum() ?? double.NaN;
}

var sum1 = SumNumbers(null, 0);
Console.WriteLine(sum1);  // output: NaN

var numberSets = new List<double[]>
{
    new[] { 1.0, 2.0, 3.0 },
    null
};

var sum2 = SumNumbers(numberSets, 0);
Console.WriteLine(sum2);  // output: 6

var sum3 = SumNumbers(numberSets, 1);
Console.WriteLine(sum3);  // output: NaN
using System;
using System.Collections.Generic;
using System.Linq;

namespace MemberAccessOperators2
{
    public static class NullConditionalShortCircuiting
    {
        public static void Main()
        {
            Person person = null;
            person?.Name.Write(); // no output: Write() is not called due to short-circuit.
            try
            {
                (person?.Name).Write();
            }
            catch (NullReferenceException)
            {
                Console.WriteLine("NullReferenceException");
            }; // output: NullReferenceException
        }
    }

    public class Person
    {
        public FullName Name { get; set; }
    }

    public class FullName
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public void Write()
        {
            Console.WriteLine($"{FirstName} {LastName}");
        }
    }
}

前面两个示例中的第一个也使用 Null 合并运算符 ?? 来指定替代表达式,以便在 null 条件运算的结果为 null 时用于计算。

如果 a.x 或 a[x] 是不可为 null 的值类型 T,则 a?.x 或 a?[x] 属于对应的可为 null 的值类型 T?。 如果需要 T 类型的表达式,请将 Null 合并操作符 ?? 应用于 null 条件表达式,如下面的示例所示:

int GetSumOfFirstTwoOrDefault(int[] numbers)
{
    if ((numbers?.Length ?? 0) < 2)
    {
        return 0;
    }
    return numbers[0] + numbers[1];
}

Console.WriteLine(GetSumOfFirstTwoOrDefault(null));  // output: 0
Console.WriteLine(GetSumOfFirstTwoOrDefault(new int[0]));  // output: 0
Console.WriteLine(GetSumOfFirstTwoOrDefault(new[] { 3, 4, 5 }));  // output: 7

在前面的示例中,如果不使用 ?? 运算符,则在 numbers 为 null 时,numbers?.Length < 2 的计算结果为 false

Null 条件成员访问运算符 ?. 也称为 Elvis 运算符。

11.线程安全的委托调用

PropertyChanged?.Invoke(…)

该代码等同于将在 C# 5 或更低版本中使用的以下代码:

var handler = this.PropertyChanged;
if (handler != null)
{
    handler(…);
}

12.这是一种线程安全方法,可确保只调用非 null handler。 由于委托实例是不可变的,因此,任何线程都不能更改 handler 本地变量所引用的对象。 具体而言,如果另一个线程执行的代码从 PropertyChanged 事件中取消订阅,并且 PropertyChanged 在调用 handler 之前变为 null,则 handler 引用的对象不受影响。 ?. 运算符对其左操作数的计算不超过一次,从而确保在验证为非 null 后,不能将其更改为 null

13.调用的表达式

使用括号 () 调用方法或调用委托

以下示例演示如何在使用或不使用参数的情况下调用方法,以及调用委托:

Action<int> display = s => Console.WriteLine(s);

var numbers = new List<int>();
numbers.Add(10);
numbers.Add(17);
display(numbers.Count);   // output: 2

numbers.Clear();
display(numbers.Count);   // output: 0

在调用带 new 运算符的构造函数时,还可以使用括号。

13.() 的其他用法

此外可以使用括号来调整表达式中计算操作的顺序。 有关详细信息,请参阅 C# 运算符

强制转换表达式,其执行显式类型转换,也可以使用括号。

14.从末尾运算符^开始索引

^ 运算符在 C# 8.0 和更高版本中提供,指示序列末尾的元素位置。 对于长度为 length 的序列,^n 指向与序列开头偏移 length - n 的元素。 例如,^1 指向序列的最后一个元素,^length 指向序列的第一个元素。

int[] xs = new[] { 0, 10, 20, 30, 40 };
int last = xs[^1];
Console.WriteLine(last);  // output: 40

var lines = new List<string> { "one", "two", "three", "four" };
string prelast = lines[^2];
Console.WriteLine(prelast);  // output: three

string word = "Twenty";
Index toFirst = ^word.Length;
char first = word[toFirst];
Console.WriteLine(first);  // output: T

 

如前面的示例所示,表达式 ^e 属于 System.Index 类型。 在表达式 ^e 中,e 的结果必须隐式转换为 int

还可以将 ^ 运算符与范围运算符一起使用以创建一个索引范围。 有关详细信息,请参阅索引和范围

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜爱Java语言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值