威尼斯www.9778.com-威尼斯正版官方网站

【转】C# 中 10 个你真的应该学习(和使用!)的功能

日期:2020-01-15编辑作者:编程人生

如果你开始探索C#或决定扩展你的知识,那么你应该学习这些有用的语言功能,这样做有助于简化代码,避免错误,节省大量的时间。

6)?.(Null条件运算符) ——C#6

null条件运算符的工作方式如下:

//Null if customer or customer.profile or customer.profile.age is null
var currentAge = customer?.profile?.age;

没有更多NullReferenceExceptions!

阅读更多有关?.-运算符的信息,请访问:

7.nameof表达式

使用场景:获取错误参数名

if (IsNullOrWhiteSpace(lastName))
    throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));

使用场景:使用INotifyPropertyChanged接口监听属性变化。

public string LastName
{
    get { return lastName; }
    set
    {
        if (value != lastName)
        {
            lastName = value;
            PropertyChanged?.Invoke(this, 
                new PropertyChangedEventArgs(nameof(LastName)));
        }
    }
}
private string lastName;

注意: NameOf只会返回Member的字符串,如果前面有对象或者命名空间,NameOf只会返回 . 的最后一部分, 另外NameOf有很多情况是不支持的,比如方法,关键字,对象的实例以及字符串和表达式

图片 1

图片 2

6.Local Functions

从 C# 7 开始,C# 支持本地函数。 本地函数是一种嵌套在另一成员中的类型的私有方法。 仅能从其包含成员中调用它们。 可以在以下位置中声明和调用本地函数:

  • 方法(尤其是迭代器方法和异步方法)
  • 构造函数
  • 属性访问器
  • 事件访问器
  • 匿名方法
  • Lambda 表达式
  • 终结器
  • 其他本地函数
using System;
using System.IO;

class Example
{
    static void Main()
    {
        string contents = GetText(@"C:temp", "example.txt");
        Console.WriteLine("Contents of the file:n" + contents);
    }

    private static string GetText(string path, string filename)
    {
         var sr = File.OpenText(AppendPathSeparator(path) + filename);
         var text = sr.ReadToEnd();
         return text;

         // Declare a local function.
         string AppendPathSeparator(string filepath)
         {
            if (! filepath.EndsWith(@""))
               filepath += @"";

            return filepath;   
         }
    } 
}

参考:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/local-functions

1)async / await

使用async / await-pattern允许在执行阻塞操作时解除UI /当前线程的阻塞。async / await-pattern的工作原理是让代码继续执行,即使在某些东西阻塞了执行(如Web请求)的情况下。

阅读更多有关async / await-pattern的信息,请访问:

2)对象/数组/集合初始化器

通过使用对象、数组和集合初始化器,可以轻松地创建类、数组和集合的实例:

//一些演示类
public class Employee {
    public string Name {get; set;}
    public DateTime StartDate {get; set;}
}

//使用初始化器创建employee 
Employee emp = new Employee {Name="John Smith", StartDate=DateTime.Now()};

上面的例子在单元测试中才真正有用,但在其他上下文中应该避免,因为类的实例应该使用构造函数创建。

阅读更多有关初始化器的信息,请访问:

4.Null 条件运算符

成员访问 (?.) :
如果value==null,则返回null

public static string Truncate(string value, int length)
{
    /
    return value?.Substring(0, Math.Min(value.Length, length));

    // C# 6.0 之前的写法
    //string result = value;
    //if (value != null)
    //{
    //    result = value.Substring(0, Math.Min(value.Length, length));
    //}
    //return result;
}

索引 (?[) 操作:

List<Example> examples = null;
Example example = examples?[0]; 
// 上述相当于 Example? item = (examples != null) ? examples[0] : null

Console.WriteLine(example == null); // 输出 True

9)as和is 运算符

is 运算符用于控制实例是否是特定类型,例如,如果你想看看是否可能转换:

if (Person is Adult)
{
    //do stuff
}

使用as运算符尝试将实例转换为类。如果不能转换,它将返回null:

SomeType y = x as SomeType;
if (y != null)
{
    //do stuff
}

7)nameof Expression ——C#6

新出来的nameof-expression可能看起来不重要,但它真的有它的价值。当使用自动重构因子工具(如ReSharper)时,你有时需要通过名称引用方法参数:

public void PrintUserName(User currentUser)
{
    //The refactoring tool might miss the textual reference to current user 
    below if we're renaming it
    if(currentUser == null)
        _logger.Error("Argument currentUser is not provided");

    //...
}

你应该这样使用它…

public void PrintUserName(User currentUser)
{
    //The refactoring tool will not miss this...
    if(currentUser == null)
        _logger.Error($"Argument {nameof(currentUser)} is not provided");

    //...
}

阅读更多有关nameof-expression的信息,请访问:

1.out 变量

//之前版本

int numericResult;
if (int.TryParse(input, out numericResult))
    WriteLine(numericResult);
else
    WriteLine("Could not parse input");

C# 7在参数列表中声明变量

if (int.TryParse(input, out int result))
    WriteLine(result);
else
    WriteLine("Could not parse input");

5)$“{x}”(字符串插值) ——C#6

这是C#6的一个新功能,可以让你用高效和优雅的方式组装字符串:

//旧方法
var someString = String.Format("Some data: {0}, some more data: {1}", someVariable, someOtherVariable);

//新方法
var someString = $"Some data: {someVariable}, some more data: {someOtherVariable}";

你可以把C#表达式放在花括号之间,这使得此字符串插值非常强大。

1)async / await

使用async / await-pattern允许在执行阻塞操作时解除UI /当前线程的阻塞。async / await-pattern的工作原理是让代码继续执行,即使在某些东西阻塞了执行(如Web请求)的情况下。

阅读更多有关async / await-pattern的信息,请访问:

3.丢弃(Discards)

从 C# 7 开始,C# 支持放弃,这是一种在应用程序代码中人为取消使用的临时虚拟变量。 放弃相当于未赋值的变量;它们没有值。 因为只有一个放弃变量,并且甚至不为该变量分配存储空间,所以放弃可减少内存分配。

场景1:元组和对象析1

var (_, _, area) = city.GetCityInformation(cityName);

public class Example
{
   public static void Main()
   {
       Person p = new Person("John", "Quincy", "Adams", "Boston", "MA");

       // <Snippet1>
       // Deconstruct the person object.
       var (fName, _, city, _) = p;
       Console.WriteLine($"Hello {fName} of {city}!");
       // The example displays the following output:
       //      Hello John of Boston!       
       // </Snippet1>
   }
}

场景2:使用 out 参数

if (DateTime.TryParse(dateString, out _)) 
            Console.WriteLine($"'{dateString}': valid");

场景3:独立丢弃

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      ExecuteAsyncMethods().Wait();
   }

   private static async Task ExecuteAsyncMethods()
   {    
      Console.WriteLine("About to launch a task...");
      _ = Task.Run(() => { var iterations = 0;  
                           for (int ctr = 0; ctr < int.MaxValue; ctr++)
                              iterations++;
                           Console.WriteLine("Completed looping operation...");
                           throw new InvalidOperationException();
                         });
      await Task.Delay(5000);                        
      Console.WriteLine("Exiting after 5 second delay");
   }
}
// The example displays output like the following:
//       About to launch a task...
//       Completed looping operation...
//       Exiting after 5 second delay

场景4:使用 switch 和 is 的模式匹配

参考:https://docs.microsoft.com/zh-cn/dotnet/csharp/discards

2)对象/数组/集合初始化器

通过使用对象、数组和集合初始化器,可以轻松地创建类、数组和集合的实例:

//一些演示类
public class Employee {
    public string Name {get; set;}
    public DateTime StartDate {get; set;}
}

//使用初始化器创建employee 
Employee emp = new Employee {Name="John Smith", StartDate=DateTime.Now()};

上面的例子在单元测试中才真正有用,但在其他上下文中应该避免,因为类的实例应该使用构造函数创建。

阅读更多有关初始化器的信息,请访问:

3)Lambdas,谓词,delegates和闭包

在许多情况下(例如使用Linq时),这些功能实际上是必需的,确保学习何时以及如何使用它们。

阅读更多关于Lambdas,谓词,delegates和闭包的信息,请访问:

6.异常过滤器(Exception Filters)

catch (ArgumentNullException e) when (e.ParamName == “…”)  
{  
}

如果括号表达式(when)的结果为 true 时,才执行对应 catch 块中的语句,否则继续搜索处理程序。

使用场景:http处理

public static async Task<string> MakeRequestWithNotModifiedSupport()
{ 
    var client = new System.Net.Http.HttpClient();
    var streamTask = client.GetStringAsync("https://localHost:10000");
    try {
        var responseText = await streamTask;
        return responseText;
    } catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
    {
        return "Site Moved";
    } catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("304"))
    {
        return "Use the Cache";
    }
}

4)??(空合并运算符)

?? – 运算符返回左侧,只要它不为null;那样的情况下返回右侧:

//可能为null
var someValue = service.GetValue();
var defaultValue = 23

//如果someValue为null,结果将为23
var result = someValue ?? defaultValue;

?? – 运算符可以链接:

string anybody = parm1 ?? localDefault ?? globalDefault;

并且它可以用于将可空类型转换为不可空:

var totalPurchased = PurchaseQuantities.Sum(kvp => kvp.Value ?? 0);

阅读更多有关?? – 运算符的信息,请访问:

9)as和is 运算符

is 运算符用于控制实例是否是特定类型,例如,如果你想看看是否可能转换:

if (Person is Adult)
{
    //do stuff
}

使用as运算符尝试将实例转换为类。如果不能转换,它将返回null:

SomeType y = x as SomeType;
if (y != null)
{
    //do stuff
}

3.导入静态类 (using static)

允许访问类型的静态成员,而无需限定使用类型名称进行访问:
r

using staticSystem.String

if (IsNullOrWhiteSpace(lastName))
    throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));

注意:扩展方法<font color=red >不能</font>使用此方式

using static System.Linq.Enumerable;
public bool MakesDeansList()
{
    return Grades.All(g => g > 3.5) && Grades.Any();
    // Code below generates CS0103: 
    // The name 'All' does not exist in the current context.
    //return All(Grades, g => g > 3.5) && Grades.Any();
}

10)yield 关键字

yield 关键字允许提供带有条目的IEnumerable接口。 以下示例将返回每个2的幂,幂指数从2到8(例如,2,4,8,16,32,64,128,256):

public static IEnumerable Power(int number, int exponent)
{
    int result = 1;
    for (int i = 0; i < exponent; i++)
    {
      result = result * number;
      yield return result;
    }
}

yield返回可以非常强大,如果它用于正确方式的话。 它使你能够懒惰地生成一系列对象,即,系统不必枚举整个集合——它就会按需完成。

4)??(空合并运算符)

?? – 运算符返回左侧,只要它不为null;那样的情况下返回右侧:

//可能为null
var someValue = service.GetValue();
var defaultValue = 23

//如果someValue为null,结果将为23
var result = someValue ?? defaultValue;

?? – 运算符可以链接:

string anybody = parm1 ?? localDefault ?? globalDefault;

并且它可以用于将可空类型转换为不可空:

var totalPurchased = PurchaseQuantities.Sum(kvp => kvp.Value ?? 0);

阅读更多有关?? – 运算符的信息,请访问:

C# 4,Visual Studio .NET 2010:

  • Dynamic、命名实参和可选实参、泛型协变和逆变。

8)属性初始化器 ——C#6

属性初始化器允许你声明属性的初始值:

public class User
{ 
    public Guid Id { get; } = Guid.NewGuid();
    // ...
}

使用属性初始化器的一个好处是你不能声明一个集合:嗯,因此使得属性不可变。属性初始化器与C#6主要构造函数语法一起工作。

10)yield 关键字

yield 关键字允许提供带有条目的IEnumerable接口。 以下示例将返回每个2的幂,幂指数从2到8(例如,2,4,8,16,32,64,128,256):

public static IEnumerable Power(int number, int exponent)
{
    int result = 1;
    for (int i = 0; i < exponent; i++)
    {
      result = result * number;
      yield return result;
    }
}

yield返回可以非常强大,如果它用于正确方式的话。 它使你能够懒惰地生成一系列对象,即,系统不必枚举整个集合——它就会按需完成。

5.ref 返回值和局部变量(ref locals and returns)

引用返回值允许方法将对象的引用(而不是值)返回给调用方。 然后,调用方可以选择将返回的对象视为按值返回或按引用返回。 如果按引用返回的值被调用方处理为引用(而非值),则该值即为 ref 局部变量。

示例

FindNumber 方法按引用返回第一个大于或等于作为参数传递的数字的数字。如果没有大于或等于该参数的数字,则方法返回索引 0 中的数字。

using System;

class NumberStore
{
   int[] numbers = { 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023 };

   public ref int FindNumber(int target)
   {
      for (int ctr = 0; ctr < numbers.Length; ctr++) {
         if (target == numbers[ctr]) {
            return ref numbers[ctr];
         }   
         else if (ctr == numbers.Length - 1) {
            return ref numbers[ctr];
         }      
         else if (target < numbers[ctr]) {
            if (ctr > 0 && target > numbers[ctr - 1])
               return ref numbers[ctr];
            else if (ctr == 0)
               return ref numbers[0];      
         }
      }
      return ref numbers[0];
   }

   public override string ToString()
   {
      string retval = "";
      for (int ctr = 0; ctr < numbers.Length; ctr++) {
         retval += $"{numbers[ctr]} ";   
      }
      return retval.Trim();   
   }
}

如示例中的输出所示,此更改将反映在 NumberStore 实例的数组元素的值中。

using System;

public class Example
{   
   static void Main(string[] args)
   {
      var store = new NumberStore();
      Console.WriteLine($"Original sequence: {store.ToString()}");
      int number = 16;
      ref var value = ref store.FindNumber(number);
      value*=2;
      Console.WriteLine($"New sequence:      {store.ToString()}");
   }
}
// The example displays the following output:
//       Original sequence: 1 3 7 15 31 63 127 255 511 1023
//       New sequence:      1 3 7 15 62 63 127 255 511 1023

参考:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/ref-returns

7)nameof Expression ——C#6

新出来的nameof-expression可能看起来不重要,但它真的有它的价值。当使用自动重构因子工具(如ReSharper)时,你有时需要通过名称引用方法参数:

public void PrintUserName(User currentUser)
{
    //The refactoring tool might miss the textual reference to current user 
    below if we're renaming it
    if(currentUser == null)
        _logger.Error("Argument currentUser is not provided");

    //...
}

你应该这样使用它…

public void PrintUserName(User currentUser)
{
    //The refactoring tool will not miss this...
    if(currentUser == null)
        _logger.Error($"Argument {nameof(currentUser)} is not provided");

    //...
}

阅读更多有关nameof-expression的信息,请访问:

如果你开始探索C#或决定扩展你的知识,那么你应该学习这些有用的语言功能,这样做有助于简化代码,避免错误,节省大量的时间。

8.throw 表达式(throw Expressions)

从 C# 7 开始,throw 可以用作表达式和语句。 这允许在以前不支持的上下文中引发异常。

条件运算符

private static void DisplayFirstNumber(string[] args)
{
   string arg = args.Length >= 1 ? args[0] : 
                              throw new ArgumentException("You must supply an argument");
   if (Int64.TryParse(arg, out var number))
      Console.WriteLine($"You entered {number:F0}");
   else
      Console.WriteLine($"{arg} is not a number.");                            

}

null 合并运算符

public string Name
{
    get => name;
    set => name = value ?? 
        throw new ArgumentNullException("Name cannot be null", nameof(value));
}

expression-bodied lambda 或方法。

DateTime ToDateTime(IFormatProvider provider) => 
         throw new InvalidCastException("Conversion to a DateTime is not supported.");

参考:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/throw#the-throw-expression

3)Lambdas,谓词,delegates和闭包

在许多情况下(例如使用Linq时),这些功能实际上是必需的,确保学习何时以及如何使用它们。

阅读更多关于Lambdas,谓词,delegates和闭包的信息,请访问:

5)$“{x}”(字符串插值) ——C#6

这是C#6的一个新功能,可以让你用高效和优雅的方式组装字符串:

//旧方法
var someString = String.Format("Some data: {0}, some more data: {1}", someVariable, someOtherVariable);

//新方法
var someString = $"Some data: {someVariable}, some more data: {someOtherVariable}";

你可以把C#表达式放在花括号之间,这使得此字符串插值非常强大。

只读自动属性(Read-only auto-properties)

只能在<font color=red >构造函数</font>或<font color=red >属性初始化表达式</font>中设置属性

public class Example
{
    public string FirstName { get; } = "Monkey";

    public string LastName { get; } 

    public Example(string lastName)
    {
        LastName = lastName;
    }
}

6)?.(Null条件运算符) ——C#6

null条件运算符的工作方式如下:

//Null if customer or customer.profile or customer.profile.age is null
var currentAge = customer?.profile?.age;

没有更多NullReferenceExceptions!

阅读更多有关?.-运算符的信息,请访问:

8)属性初始化器 ——C#6

属性初始化器允许你声明属性的初始值:

public class User
{ 
    public Guid Id { get; } = Guid.NewGuid();
    // ...
}

使用属性初始化器的一个好处是你不能声明一个集合:嗯,因此使得属性不可变。属性初始化器与C#6主要构造函数语法一起工作。

2. 表达式主体(Expression-bodied function members)

通过表达式主体定义,可采用非常简洁的可读形式提供成员的实现
语法:

member => expression;

C#6支持:属性Get、方法

    //方法的表达式主体定义
    private static string SayHello() => "Hello World";
    //属性Get的表达式主体定义
    public string FullName => $"{FirstName} {LastName}";

本文由码农网 – 小峰原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

5.字符串插值 (String Interpolation)

public string GetFormattedGradePoint() =>
    $"Name: {LastName}, {FirstName}. G.P.A: {Grades.Average()}";

public string GetGradePointPercentage() =>
    $"Name: {LastName}, {FirstName}. G.P.A: {Grades.Average():F2}";

public string GetGradePointPercentages() =>
    $"Name: {LastName}, {FirstName}. G.P.A: {Grades.Any() ? Grades.Average() : double.NaN:F2}";

public string GetGradePointPercentages() =>
    $"Name: {LastName}, {FirstName}. G.P.A: {(Grades.Any() ? Grades.Average() : double.NaN):F2}";

public string GetAllGrades() =>
    $@"All Grades: {Grades.OrderByDescending(g => g)
    .Select(s => s.ToString("F2")).Aggregate((partial, element) => $"{partial}, {element}")}";

9.Generalized async return types

C# 1.1,Visual Studio .NET 2003:

  • /#line 杂注和 xml 文档注释。
自动属性初始化表达式。
    public class Example
    {
        // 6.0新增语法糖:属性初始化表达式
        public string FirstName { get; set; } = "Monkey";

        // 6.0之前的写法
        private string _firstName = "Monkey";
        public string FirstName
        {
            get { return _firstName; }
            set { _firstName = value; }
        }
    }

9.索引初始化器(Index Initializers)

private List<string> messages = new List<string> 
{
    "Page not Found",
    "Page moved, but left a forwarding address.",
    "The web server can't come out to play today."
};

private Dictionary<int, string> webErrors = new Dictionary<int, string>
{
    [404] = "Page not Found",
    [302] = "Page moved, but left a forwarding address.",
    [500] = "The web server can't come out to play today."
};

2.元组(Tuples)

需要引用包:System.ValueTuple

元组是轻量级数据结构,包含多个字段来表示数据成员

var unnamed = ("one", "two");//字段名称为 Item1、Item2、Item3......

var named = (first: "one", second: "two");

(string Alpha, string Beta) namedLetters = ("a", "b");

var alphabetStart = (Alpha: "a", Beta: "b");

元组最适合作为private和internal方法的返回类型,如 分页结果集中的数据和总行数

private static (int Max, int Min) Range(IEnumerable<int> numbers)
{
    int min = int.MaxValue;
    int max = int.MinValue;
    foreach(var n in numbers)
    {
        min = (n < min) ? n : min;
        max = (n > max) ? n : max;
    }
    return (max, min);
}

参考:https://docs.microsoft.com/zh-cn/dotnet/csharp/tuples

参考

https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/

二、C# 6 的新功能 (Visual Studio .NET 2015)

8.在 catch 和 finally 块使用关键字 await

public static async Task<string> MakeRequestAndLogFailures()
{ 
    await logMethodEntrance();
    var client = new System.Net.Http.HttpClient();
    var streamTask = client.GetStringAsync("https://localHost:10000");
    try {
        var responseText = await streamTask;
        return responseText;
    } catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
    {
        await logError("Recovered from redirect", e);
        return "Site Moved";
    }
    finally
    {
        await logMethodExit();
        client.Dispose();
    }
}

C# 1,Visual Studio .NET 2002:

  • C# 初版。

三、C# 7 的新功能(Visual Studio .NET 2017)

10.数字语法改进(Numeric literal syntax improvements)

二进制

public const int One =  0b0001;
public const int Two =  0b0010;
public const int Four = 0b0100;
public const int Eight = 0b1000;

数字分隔符

public const long BillionsAndBillions = 100_000_000_000;
public const double AvogadroConstant = 6.022_140_857_747_474e23;
public const decimal GoldenRatio = 1.618_033_988_749_894_848_204_586_834_365_638_117_720_309_179M;

C# 2,Visual Studio .NET 2005:

  • 匿名方法、泛型、可空类型、迭代器/yield、static 类、委托的协变和逆变。

C#新功能

一、C#历史演变

1. 扩展自动属性语法

4.模式匹配(Pattern Matching)

is 类型模式表达式:优化原有语法

public static double ComputeAreaModernIs(object shape)
{
    if (shape is Square s)
        return s.Side * s.Side;
    else if (shape is Circle c)
        return c.Radius * c.Radius * Math.PI;
    else if (shape is Rectangle r)
        return r.Height * r.Length;
    // elided
    throw new ArgumentException(
        message: "shape is not a recognized shape",
        paramName: nameof(shape));
}

编写 if (!(shape is Square s)) 来反转逻辑,变量 s 会只在 false 分支中进行明确赋值。

使用模式匹配 switch 语句

public static double ComputeAreaModernSwitch(object shape)
{
    switch (shape)
    {
        case Square s:
            return s.Side * s.Side;
        case Circle c:
            return c.Radius * c.Radius * Math.PI;
        case Rectangle r:
            return r.Height * r.Length;
        default:
            throw new ArgumentException(
                message: "shape is not a recognized shape",
                paramName: nameof(shape));
    }
}

case 表达式中的 when 语句

public static double ComputeArea_Version5(object shape)
{
    switch (shape)
    {
        case Square s when s.Side == 0:
        case Circle c when c.Radius == 0:
        case Triangle t when t.Base == 0 || t.Height == 0:
        case Rectangle r when r.Length == 0 || r.Height == 0:
            return 0;

        case Square s:
            return s.Side * s.Side;
        case Circle c:
            return c.Radius * c.Radius * Math.PI;
        case Triangle t:
            return t.Base * t.Height * 2;
        case Rectangle r:
            return r.Length * r.Height;
//重点
        case null:
            throw new ArgumentNullException(paramName: nameof(shape), message: "Shape must not be null");
        default:
            throw new ArgumentException(
                message: "shape is not a recognized shape",
                paramName: nameof(shape));
    }
}

参考:https://docs.microsoft.com/zh-cn/dotnet/csharp/pattern-matching

C# 5,Visual Studio .NET 2012:

  • Async / await 和调用方信息特性

7.更多的表达式主体成员(More expression-bodied members)

C#7支持:构造函数,终结器,属性 Set 语句,索引器

构造函数

public class Location
{
   private string locationName;

   public Location(string name) => locationName = name;
}

终结器

using System;

public class Destroyer
{
   public override string ToString() => GetType().Name;

   ~Destroyer() => Console.WriteLine($"The {ToString()} destructor is executing.");
}

属性 Set 语句,

public class Location
{
   public string Name
   {
      get => locationName;
      set => locationName = value;
   } 
}

索引器

using System;
using System.Collections.Generic;

public class Sports
{
   private string[] types = { "Baseball", "Basketball", "Football", 
                              "Hockey", "Soccer", "Tennis", 
                              "Volleyball" }; 

   public string this[int i]
   {
      get => types[i];
      set => types[i] = value;
   }
}

参考:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/statements-expressions-operators/expressions#expression-body-definitions

C# 3,Visual Studio .NET 2008:

  • 对象和集合初始值设定项、lambda 表达式、扩展方法、匿名类型、自动属性、本地 var 类型推理和语言集成查询 (LINQ)。

本文由威尼斯www.9778.com发布于编程人生,转载请注明出处:【转】C# 中 10 个你真的应该学习(和使用!)的功能

关键词:

Google C++ 编程风格指南:作用域

通常每一个  .cc  文件都有一个对应的  .h  文件. 也有一些常见例外,如单元测试代码和只包含  main()  函数的  .c...

详细>>

C++ 中三种正则表明式相比较

3、boost regex /* write by xingming * for:test boost regex * time:2012年10月23日11:35:33 * */#include iostream#include string#include sys/time.h#in...

详细>>

威尼斯正版官方网站new与malloc的10点区别

堆内存 vs. 内存池 Allocator类在“释放列表”为空时,能够从堆内存或者内存池中申请新内存。如果使用内存池,你必...

详细>>