C#关键字
is
is关键字在运行时评估类型的兼容性。他它确定对象实例或表达式结果是否可以转换为指定类型。
语法:expr is type
如果可以转换,则返回true,否则返回false;
满足下列条件,is语句为true:
- expr 是与 type 具有相同类型的一个实例。
- expr 是派生自 type 的类型的一个实例。 换言之,expr 结果可以向上转换为 type 的一个实例。
- expr 具有属于 type 的一个基类的编译时类型,expr 还具有属于 type 或派生自 type 的运行时类型。 变量的编译时类型是其声明中定义的变量类型。 变量的运行时类型是分配给该变量的实例类型。
- expr 是实现 type 接口的类型的一个实例。
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 运算符:用于创建对象和调用构造函数。
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;
}
}
属性
- 如上例,
- 不使用显式 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;
}
}