base
在C#中,base 关键字用于访问基类(父类)的成员,包括字段、属性、方法、事件等。当在派生类中需要调用基类中的成员时,可以使用 base 关键字。这在你需要扩展或修改基类功能,但仍需要调用基类版本的成员时非常有用。
以下是一些使用 base 关键字的例子:
- 调用基类构造函数
public class BaseClass
{
public BaseClass()
{
Console.WriteLine("BaseClass constructor called.");
}
}
public class DerivedClass : BaseClass
{
public DerivedClass() : base()
{
Console.WriteLine("DerivedClass constructor called.");
}
}
class Program
{
static void Main()
{
DerivedClass d = new DerivedClass();
}
}
输出:
BaseClass constructor called.
DerivedClass constructor called.
在这个例子中,DerivedClass 的构造函数使用 base() 来调用 BaseClass 的构造函数。
- 调用基类方法
public class BaseClass
{
public void DoSomething()
{
Console.WriteLine("Doing something in BaseClass.");
}
}
public class DerivedClass : BaseClass
{
public new void DoSomething()
{
base.DoSomething(); // 调用基类的 DoSomething 方法
Console.WriteLine("Doing something else in DerivedClass.");
}
}
class Program
{
static void Main()
{
DerivedClass d = new DerivedClass();
d.DoSomething();
}
}
输出:
Doing something in BaseClass.
Doing something else in DerivedClass.
在这个例子中,DerivedClass 重写了 DoSomething 方法,但在新的实现中,它首先使用 base.DoSomething() 来调用基类版本的 DoSomething 方法。
- 访问基类字段或属性
public class BaseClass
{
public int MyProperty { get; set; }
}
public class DerivedClass : BaseClass
{
public void ShowProperty()
{
Console.WriteLine($"The value of MyProperty is: {base.MyProperty}");
}
}
class Program
{
static void Main()
{
DerivedClass d = new DerivedClass();
d.MyProperty = 42;
d.ShowProperty();
}
}
输出:
The value of MyProperty is: 42
在这个例子中,DerivedClass 通过 base.MyProperty 访问了基类 BaseClass 的 MyProperty 属性。
通过使用 base 关键字,你可以确保在扩展基类功能时不会丢失或破坏基类的现有功能。这有助于维
护代码的一致性和可维护性。
using
在C#中,using 关键字主要用于两种场景:
定义别名:为命名空间或类型定义别名,以便在代码中更简洁地引用它们。这通常在引用长命名空间或当两个命名空间中有相同名称的类型时很有用。
using MyAlias = Some.Long.Namespace.TypeName;
确保资源的正确释放:与实现了 IDisposable 接口的对象一起使用,确保对象在使用完毕后其资源被正确释放。这是using语句最常见的用法,“提供自动回收”的场景。
当使用实现了 IDisposable 接口的对象时(如文件句柄、数据库连接、网络套接字等),为了确保这些对象在使用完毕后能够释放其占用的非托管资源,应该使用 using 语句。using 语句会确保在代码块执行完毕后调用对象的 Dispose 方法,即使发生异常也会如此。
using (var resource = new ResourceThatImplementsIDisposable())
{
// 使用 resource 对象
} // 在这里,resource.Dispose() 会被自动调用
在上述代码中,当控制流离开 using 块时,无论是因为正常执行完毕还是因为发生了异常,resource 对象的 Dispose 方法都会被自动调用。这有助于防止资源泄漏和其他与资源管理相关的问题。
因此,你应该在以下情况下使用 using 语句:
当你使用实现了 IDisposable 接口的对象时。
当你想要确保对象在使用完毕后其资源得到正确释放时。
请注意,using 语句仅适用于局部作用域中的对象。对于类的字段或属性等成员变量,通常需要在类的 Dispose 方法(如果类也实现了 IDisposable)中显式释放资源。
yield
在C#中,yield关键字用于在迭代器块中,它允许你创建一个可以逐个返回元素(而不是一次性返回所有元素)的自定义迭代器。使用yield,你可以编写一个方法,它像返回一个集合一样工作,但实际上每次只生成一个元素。这对于处理大量数据或执行需要逐个元素处理的复杂计算特别有用,因为它允许你以更内存高效的方式处理数据。
yield有两种形式:yield return和yield break。
yield return
yield return语句用于在迭代器的每次迭代中返回一个值。当迭代器块被调用时,它不会立即执行,而是返回一个可枚举的对象。当你开始枚举这个对象时,迭代器块的代码会开始执行,直到遇到第一个yield return语句,此时它会返回该值,并暂停执行。下一次枚举时,它会从上次暂停的地方继续执行,直到遇到下一个yield return语句或迭代结束。
示例:
public IEnumerable<int> GetNumbers()
{
for (int i = 0; i < 10; i++)
{
yield return i;
}
}
在这个例子中,GetNumbers方法返回一个IEnumerable,但它不会立即生成所有数字。相反,当你开始枚举这个返回的对象时,它会逐个生成数字0到9。
yield break
yield break语句用于在迭代器块中提前终止迭代。如果在迭代过程中满足某个条件,你可以使用yield break来停止迭代并退出迭代器块。
示例:
public IEnumerable<int> GetNumbersUpTo(int limit)
{
for (int i = 0; i < int.MaxValue; i++)
{
if (i >= limit)
{
yield break; // 当i达到或超过limit时停止迭代
}
yield return i;
}
}
在这个例子中,GetNumbersUpTo方法会根据提供的limit参数来生成数字。当生成的数字达到或超过limit时,yield break语句会被执行,迭代会提前终止。
使用yield的关键好处是它可以让你以更简洁和内存高效的方式编写生成器逻辑,而不需要显式地管理集合或数组的内存分配。这对于处理大量数据或流式处理数据特别有用。