C# 编程效率提升指南:掌握算数运算、循环与方法封装
在这篇文章中将带你深入探索C#中的几大关键技术点,从如何精准进行算数运算、灵活运用循环控制结构,到通过方法封装提升代码的复用性,再到正确使用可空类型避免潜在的空值引用异常,这些概念和技巧无一不是编写清晰、高效、健壮代码的必备武器。
目录
C#算数运算
C#循环判断
C#封装方法
C#可空类型
C#算数运算
运算符是一种告诉编译器执行特定的数学或逻辑操作的符号,在C#中有丰富的内置运算符,接下来就这些运算符的使用作一个简单的介绍:
算术运算符:下表是C#支持的所有算术运算符,假设变量A的值为10,变量B的值为20则:
运算符 | 描述 | 实例 |
---|---|---|
+ | 把两个操作数相加 | A + B 将得到 30 |
- | 从第一个操作数中减去第二个操作数 | A - B 将得到 -10 |
* | 把两个操作数相乘 | A * B 将得到 200 |
/ | 分子除以分母 | B / A 将得到 2 |
% | 取模运算符,整除后的余数 | B % A 将得到 0 |
++ | 自增运算符,整数值增加 1 | A++ 将得到 11 |
-- | 自减运算符,整数值减少 1 | A-- 将得到 9 |
其中自增和自减运算符有两种情况,一种是前置自增(减);另一种是后置自增(减):
c = a++ // 先将 a 赋值给 c,再对 a 进行自增运算。
c = ++a // 先将 a 进行自增运算,再将 a 赋值给 c 。
c = a-- // 先将 a 赋值给 c,再对 a 进行自减运算。
c = --a // 先将 a 进行自减运算,再将 a 赋值给 c 。
逻辑运算符:下表是C#支持的所有逻辑运算符,假设变量A为布尔值 true,变量B为布尔值 false,则:
运算符 | 描述 | 实例 |
---|---|---|
&& | 称为逻辑与运算符,如果两个操作数都非零,则条件为真。 | (A && B) 为假。 |
|| | 称为逻辑或运算符,如果两个操作数中有任意一个非零,则条件为真。 | (A || B) 为真。 |
! | 称为逻辑非运算符,如果条件为真则逻辑非运算符将使其为假。 | !(A && B) 为真。 |
赋值运算符:下表列出了C#支持的赋值运算符:
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符,把右边操作数的值赋给左边操作数 | C = A + B 将把 A + B 的值赋给 C |
+= | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 | C += A 相当于 C = C + A |
-= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 | C -= A 相当于 C = C - A |
*= | 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 | C *= A 相当于 C = C * A |
/= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 | C /= A 相当于 C = C / A |
%= | 求模且赋值运算符,求两个操作数的模赋值给左边操作数 | C %= A 相当于 C = C % A |
<<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
>>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
|= | 按位或且赋值运算符 | C |= 2 等同于 C = C | 2 |
其他运算符:下表列出了C#支持的其他一些重要的运算符,包括sizeof、typeof和? ,如下:
运算符 | 描述 | 实例 |
---|---|---|
sizeof() | 返回数据类型的大小。 | sizeof(int),将返回 4. |
typeof() | 返回 class 的类型。 | typeof(StreamReader); |
& | 返回变量的地址。 | &a; 将得到变量的实际地址。 |
* | 变量的指针。 | *a; 将指向一个变量。 |
? : | 条件表达式 | 如果条件为真 ? 则为 X : 否则为 Y |
is | 判断对象是否为某一类型。 | If( Ford is Car) // 检查 Ford 是否是 Car 类的一个对象。 |
as | 强制转换,即使转换失败也不会抛出异常。 | Object obj = new StringReader("Hello"); StringReader r = obj as StringReader; |
C#循环判断
循环:在C#中循环是一种控制结构,用于重复执行一段代码直到满足特定的条件为止,循环使得代码更加简洁避免了手动重复编写相同的语句,提高了程序的效率和可维护性,C#提供了以下几种循环类型:
while循环:当给定条件为真时,重复语句或语句组,它会在执行循环主体之前测试条件。
using System;
namespace Loops
{
class Program
{
static void Main(string[] args)
{
int a = 10; // 局部变量定义
while (a < 20) // while 循环执行
{
Console.WriteLine("a 的值: {0}", a);
a++;
}
Console.ReadLine();
}
}
}
for/foreach循环:多次执行一个语句序列,简化管理循环变量的代码。
using System;
namespace Loops
{
class Program
{
static void Main(string[] args)
{
for (int a = 10; a < 20; a = a + 1) // for 循环执行
{
Console.WriteLine("a 的值: {0}", a);
}
Console.ReadLine();
}
}
}
do...while循环:除了它是在循环主体结尾测试条件外,其他与 while 语句类似,该循环会确保至少执行一次循环。
using System;
namespace Loops
{
class Program
{
static void Main(string[] args)
{
int a = 10; // 局部变量定义
do // do 循环执行
{
Console.WriteLine("a 的值: {0}", a);
a = a + 1;
} while (a < 20);
Console.ReadLine();
}
}
}
嵌套循环:可以在 while、for 或 do..while 循环内使用一个或多个循环。
do
{
statement(s);
do
{
statement(s);
}while( condition );
}while( condition );
循环控制语句更改执行的正常序列,当执行离开一个范围时所有在该范围中创建的自动对象都会被销毁,C#提供了下列的控制语句:
控制语句 | 描述 |
---|---|
break语句 | 终止loop或switch语句,程序流将继续执行紧接着loop活switch下一条语句 |
continue语句 | 跳过本轮循环,开始下一轮循环 |
判断:判断是通过条件语句来实现的,常见的条件语句有 if 语句、else if 语句、else 语句、以及 switch 语句,判断使得程序可以根据不同的输入或状态做出不同的反应,这和其他编程语言类似,这里就不再赘述了:
语句 | 描述 |
---|---|
if语句 | if语句由一个布尔表达式后跟一个或多个语句组成 |
if...else语句 | if语句后可跟一个可选的else语句,else语句在布尔表达式为假时执行 |
嵌套if语句 | 可以在一个if或else if语句内使用另一个if或else if语句 |
switch语句 | switch语句允许测试一个变量等于多个值的情况 |
嵌套switch语句 | switch语句内使用另一个switch语句 |
C#封装方法
封装:面向对象编程(OOP)的四大基本特性之一,指的是将对象的状态(数据)和行为(方法包装在一个单独的类或对象中,并通过定义公共接口(方法)与外部进行交互,同时隐藏对象内部的具体实现细节,封装在C#中通常通过访问修饰符来控制数据成员和方法的可见性,常用的访问修饰符包括:
1)public:公开访问,外部代码可以访问。
2)private:私有访问,外部代码无法直接访问。
3)protected:受保护访问,仅限当前类及其子类访问。
4)internal:内部访问,只能在当前程序集内访问。
5)protected internal:访问限于当前程序集或派生自包含类的类型。
Internal访问修饰符允许一个类将其成员变量和成员函数暴露给当前程序中的其他函数和对象,换句话说带有internal访问修饰符的任何成员可以被定义在该成员所定义的应用程序内的任何类或方法访问,下面的实例说明了这点:
using System;
namespace RectangleApplication
{
class Rectangle
{
//成员变量
internal double length;
internal double width;
double GetArea()
{
return length * width;
}
public void Display()
{
Console.WriteLine("长度: {0}", length);
Console.WriteLine("宽度: {0}", width);
Console.WriteLine("面积: {0}", GetArea());
}
}//end class Rectangle
class ExecuteRectangle
{
static void Main(string[] args)
{
Rectangle r = new Rectangle();
r.length = 4.5;
r.width = 3.5;
r.Display();
Console.ReadLine();
}
}
}
总结来说,封装就是将数据和方法组织到一个单独的类中,隐藏细节,暴露接口,保证数据的完整性和安全性,简化程序的使用和维护,以下是封装的具体优势:
1)提高安全性:通过封装可以控制对数据的访问和修改,防止外部错误的修改或非法访问。
2)简化使用:外部代码只需要关注接口,减少了与内部实现的耦合,易于维护。
3)增强可维护性和扩展性:可以在不改变接口的情况下修改内部实现,不影响外部使用。
方法:是类或结构体中的一个成员,定义了可以执行的操作或功能用于封装执行某些任务的代码,通过函数名来调用并可以接受输入参数返回结果,在C#中定义方法的语法如下所示:
// Access Specifier:访问修饰符,这个决定了变量或方法对于另一个类的可见性。
// Return type:返回类型,一个方法可以返回一个值。返回类型是方法返回的值的数据类型。如果方法不返回任何值,则返回类型为 void。
// Method name:方法名称,是一个唯一的标识符,且是大小写敏感的。它不能与类中声明的其他标识符相同。
// Parameter list:参数列表,使用圆括号括起来,该参数是用来传递和接收方法的数据。参数列表是指方法的参数类型、顺序和数量。参数是可选的,也就是说,一个方法可能不包含参数。
// Method body:方法主体,包含了完成任务所需的指令集。
<Access Specifier> <Return Type> <Method Name>(Parameter List)
{
Method Body
}
下面的代码片段显示一个函数FindMax,它接受两个整数值并返回两个中的较大值,它有public访问修饰符,所以它可以使用类的实例从类的外部进行访问,可以使用方法名调用方法,如下:
using System;
namespace CalculatorApplication
{
class NumberManipulator
{
public int FindMax(int num1, int num2)
{
/* 局部变量声明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
static void Main(string[] args)
{
/* 局部变量定义 */
int a = 100;
int b = 200;
int ret;
NumberManipulator n = new NumberManipulator();
//调用 FindMax 方法
ret = n.FindMax(a, b);
Console.WriteLine("最大值是: {0}", ret );
Console.ReadLine();
}
}
}
C#可空类型
可空类型(Nullable Types):是一种允许值类型(如int、double、bool等)可以表示空值(null)的机制,通常值类型不能为null,但通过可空类型可以让它们也具备表示缺失值或空值的能力,这对于处理数据库或其他需要表示缺失数据的场景非常有用。
可空类型是通过在值类型后加上一个问号 ? 来声明的,例如 int? 表示一个可空的整数类型,可以包含一个整数值或者是null(表示没有值),如下所示:
int? y = null; // y 是一个可空整数类型
int? x = 10;
if (x.HasValue)
{
Console.WriteLine($"x 的值是 {x.Value}");
}
else
{
Console.WriteLine("x 是 null");
}
访问可空类型的值:如果确定可空类型的值不为 null,可以通过.Value属性来访问它的值:
int? x = 5;
int value = x.Value; // 这里不会抛出异常,因为 x 有值
使用可空类型的默认值:可以使用 ?? 运算符为可空类型提供一个默认值,当其为 null 时使用默认值:
int? x = null;
int result = x ?? 0; // 如果 x 是 null,result 将为 0
总结:
1)可空类型使得值类型可以表示 null,这是通过在类型后加上 ? 实现的。
2)可空类型常用于处理可能为空的值,如数据库操作或表示缺失数据。
3)使用时需要检查 HasValue 或者通过 ?? 提供默认值,以避免 null 引起的错误。