C#关键字

is

is关键字在运行时评估类型的兼容性。他它确定对象实例或表达式结果是否可以转换为指定类型。

语法:expr is type

如果可以转换,则返回true,否则返回false;

满足下列条件,is语句为true:

expr是type类型或其子类,则为真。 object是任意类型的隐性父类。

利用is进行模式匹配

使用类型模式执行模式匹配时,is 会测试表达式是否可转换为指定类型,如果可以,则将其转换为该类型的一个变量。

语法:expr is type varname

public class Employee : IComparable
{
    public String Name { get; set; }
    public int Id { get; set; }

    public int CompareTo(Object o)
    {
        if (o is Employee e)
        {
            return Name.CompareTo(e.Name);
        }
        throw new ArgumentException("o is not an Employee object.");
    }
}

与下式等价

public class Employee : IComparable
{
    public String Name { get; set; }
    public int Id { get; set; }

    public int CompareTo(Object o)
    {
        var e = o as Employee;
        if (e == null)
        {
           throw new ArgumentException("o is not an Employee object.");
        }
        return Name.CompareTo(e.Name);
    }
}

常量模式

使用常量模式执行模式匹配时,is 会测试表达式结果是否等于指定常量

语法:expr is constant

var模式

具有 var 模式的模式匹配始终成功。可以向varname的变量分配表达式

语法:expr is var varname

as

可以使用as运算符在符合的引用类型或可以为null的类型之间执行类型的转换,若无法进行转换,则返回null。

语法:expr as type

与下式等价: expr is type?(type) expr :(type) null

请注意,as 运算符仅执行引用转换、可以为 null 的转换和装箱转换。 as 运算符无法执行其他转换,例如用户定义的转换,应使用转换表达式执行此转换。

class Base
    {
        public override string  ToString()
        {
           return "Base";
        }
    }
    class Derived : Base 
    { }

    class Program
    {
        static void Main()
        {

            Derived d = new Derived();

            Base b = d as Base;
            if (b != null)
            {
                Console.WriteLine(b.ToString());
            }

        }
    }

new

new和 override—多态性

默认的访问顺序:具有 BaseClass 类型的变量继续访问 BaseClass 的成员,而具有 DerivedClass 类型的变量首先继续访问 DerivedClass 中的成员,然后再考虑从 BaseClass 继承的成员。

在用作声明修饰符时,new 关键字可以显式隐藏从基类继承的成员。 隐藏继承的成员时,该成员的派生版本将替换基类版本。 虽然可以不使用 new 修饰符来隐藏成员,但将收到编译器警告。 如果使用 new 来显式隐藏成员,将禁止此警告。

在 C# 中,派生类中的方法可具有与基类中的方法相同的名称。 可使用 new 和 override 关键字指定方法的交互方式。 override 修饰符用于扩展基类方法,而 new 修饰符则用于隐藏该方法。

class BaseClass  
{  
    public void Method1()  
    {  
        Console.WriteLine("Base - Method1");  
    }  
}  

class DerivedClass : BaseClass  
{  
    public void Method2()  
    {  
        Console.WriteLine("Derived - Method2");  
    }  
}  
class Program  
{  
    static void Main(string[] args)  
    {  
        BaseClass bc = new BaseClass();  
        DerivedClass dc = new DerivedClass();  
        BaseClass bcdc = new DerivedClass(); 
        // bcdc 为 BaseClass 类型,其值为 DerivedClass 类型。 需注意此变量。 

        bc.Method1();  
        dc.Method1();  
        dc.Method2();  
        bcdc.Method1();  
    }  
    // Output:  
    // Base - Method1  
    // Base - Method1  
    // Derived - Method2  
    // Base - Method1  
} 

由于 bc 和 bcdc 具有 BaseClass 类型,因此它们只能直接访问 Method1,除非使用强制转换。

现在将Method2添加到BaseClass.

public void Method2()  
{  
    Console.WriteLine("Base - Method2");  
}  
//运行:
bc.Method1();   // Base - Method1  
bc.Method2();  // Base - Method2
dc.Method1();  // Base - Method1  
dc.Method2();  // Derived - Method2 
bcdc.Method1();  // Base - Method1 
bcdc.Method2(); // Base - Method2  

//添加到DerivedClass,在baseclass中添加virtual
public override void Method1()  
{  
    Console.WriteLine("Derived - Method1");  
} 
//再次运行:
// Base - Method1  
// Base - Method2  
// Derived - Method1  
// Derived - Method2  
// Derived - Method1  
// Base - Method2 

构造函数

不加访问修饰符的构造函数为私有。

默认构造函数

如果没有为类提供构造函数,默认情况下,C# 将创建一个会实例化对象并将成员变量设置为默认值的构造函数,如默认值表中所列。

静态构造函数

前面的示例具有所有已展示的实例构造函数,这些构造函数创建一个新对象。 类或结构也可以具有静态构造函数,该静态构造函数初始化类型的静态成员。也可以使用表达式主体。

public class Adult : Person
{
   private static int minimumAge;
   
   public Adult(string lastName, string firstName) : base(lastName, firstName)
   { }

   static Adult()
   {
      minimumAge = 18;
   }

   // Remaining implementation of Adult class.
}

复制构造函数

class Person
{
    // Copy constructor.
    public Person(Person previousPerson)
    {
        Name = previousPerson.Name;
        Age = previousPerson.Age;
    }
    // Alternate copy constructor calls the instance constructor.
    //public Person(Person previousPerson)
    //    : this(previousPerson.Name, previousPerson.Age)
    //{
    //}

    // Instance constructor.
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
    public int Age { get; set; }
    public string Name { get; set; }
    public string Details()
    {
        return Name + " is " + Age.ToString();
    }
}

表达式主体(expression-bodied)

通过表达式主体定义,可采用非常简洁的可读形式提供成员的实现。 只要任何支持的成员(如方法或属性)的逻辑包含单个表达式,就可以使用表达式主体定义。 表达式主体定义具有下列常规语法: member=>expr;

方法

public class Person
{
   public Person(string firstName, string lastName)
   {
      fname = firstName;
      lname = lastName;
   }

   private string fname;
   private string lname;
   
   public override string ToString() => $"{fname} {lname}".Trim();
   public void DisplayName() => Console.WriteLine(ToString());
}

class Example
{
   static void Main()
   {
      Person p = new Person("Mandy", "Dejesus");
      Console.WriteLine(p);
      p.DisplayName();
   }
}

构造函数

public class Location
{
   private string locationName;
   
   public Location(string name) => locationName = name;

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

属性

  1. 如上例,
  2. 不使用显式 set 语句也可实现使用表达式主体定义的只读属性。 语法为: propertyname=>returnvalue;
    public string Name => locationName;
    

索引器

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;
   }
}