【学习笔记】C#基础 - 由C/C++衍生出来的面向对象的编程语言

这篇具有很好参考价值的文章主要介绍了【学习笔记】C#基础 - 由C/C++衍生出来的面向对象的编程语言。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、程序结构

1、基本语法

using System; // C#程序第一条语句都是 using System; 
// using 关键字(可多个):在程序中包含命名空间

namespace RectangleApplication // namespace 声明(可多个):包含一系列的类
{
    class Rectangle // class 声明(可多个):包含程序数据和方法声明
    {
        double width; // 变量声明:类的属性或数据成员,用于存储数据
        double length;

        public void Acceptdetails() // 函数声明:一系列执行指定任务的语句
        {
            width = 3.5;
            length = 4.5;
        }
        public double GetArea()
        {
            return width * length;
        }
        public void Display()
        {
            Console.WriteLine("Length:{0}", length);
            Console.WriteLine("Width: {0}", width);
            Console.WriteLine("Area: {0}", GetArea());
        }
    }
    class ExecuteRectangle // 实例化 Rectangle 的类
    {
        static void Main(string[] args) // Main 方法:定义类的动作(所有 C# 程序的入口点,程序执行从此开始)
        {
            Rectangle r = new Rectangle(); // 实例化 Rectangle
            r.Acceptdetails();
            r.Display();
            Console.ReadLine(); // 输出内容
        }
    }
}

2、类的命名

  1. 必须以 A-Z / _ / @ 开头,不能是数字,之后可以跟 A-Z0-9_@
  2. 不能包含任何空格或特殊符号,比如 ?-+!#%^&*()[]{}.;:"'/\
  3. 不能与关键字同名(除非添加 @ 前缀,@不作为标识符本身的一部分),不能与类库同名
  4. 必须区分大小写(PascalCase命名法)

3、关键字

  • 保留关键字
    abstract as base bool break byte case catch char checked class const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in in(generic modifier) int interface internal is lock long namespace new null object operator out out(generic modifier) override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual void volatile while

  • 上下文关键字
    add alias ascending descending dynamic from get global group into join let orderby partial(type) partial(method) remove select set

二、数据类型

1、值(Value)类型

直接包含数据,当声明一个值类型时,系统分配内存来存储值

类型 描述 范围 默认值
bool 布尔值 True 或 False False
byte 8 位无符号整数 0 到 255 0
char 16 位 Unicode 字符 U +0000 到 U +ffff '\0'
decimal 128 位精确的十进制值,28-29 有效位数 (-7.9 x 1028 到 7.9 x 1028) / 100 到 28 0.0M
double 64 位双精度浮点型 (+/-)5.0 x 10-324 到 (+/-)1.7 x 10308 0.0D
float 32 位单精度浮点型 -3.4 x 1038 到 + 3.4 x 1038 0.0F
int 32 位有符号整数类型 -2,147,483,648 到 2,147,483,647 0
long 64 位有符号整数类型 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 0L
sbyte 8 位有符号整数类型 -128 到 127 0
short 16 位有符号整数类型 -32,768 到 32,767 0
uint 32 位无符号整数类型 0 到 4,294,967,295 0
ulong 64 位无符号整数类型 0 到 18,446,744,073,709,551,615 0
ushort 16 位无符号整数类型 0 到 65,535 0
int i = 75;
float f = 53.005f;
double d = 2345.7652;
bool b = true;

Console.WriteLine("Size of int: {0}", sizeof(int)); // 获取任何机器上 int 类型的存储尺寸

2、引用(Reference)类型

不包含实际数据,仅包含对变量的引用(指向一个内存位置)

  • 对象类型object:通用类型系统中所有数据类型的终极基类,可以被分配任何其他数据类型的值(分配值之前需先进行类型转换)
int i = 10;
object obj = i; // 装箱:将一个值类型转换为对象类型
int j = (int)obj; // 拆箱:将一个对象类型转换为值类型

// 拆箱时强转的值类型,应与装箱时的值类型一致

装箱:在堆中自动创建一个对象实例,然后将该值复制到新对象内
【学习笔记】C#基础 - 由C/C++衍生出来的面向对象的编程语言,学习笔记,c#,c语言,c++,学习笔记

拆箱:检查是否是给定值类型的一个装箱值,然后将该值从实例复制到值类型变量中

  • 动态类型dynamic:存储任何类型的值,动态类型变量的类型检查是在运行时发生的
/* 声明动态类型的语法 */
dynamic <variable_name> = value;

dynamic d = 20;
  • 字符串类型string:允许给变量分配任何字符串值(两种分配形式:引号和 @引号)
/* 声明字符串类型的语法 */
string <variable_name> = value;

String str = "runoob.com";
string str = @"C:\Windows"; // 字符串前加 @ 可取消字符串中\的转义,将内容原样输出
string str = @"<script type=""text/javascript"">
    <!--
    -->
</script>"; // @字符串内容可换行书写,换行符及缩进空格都计算在字符串长度之内

3、指针(Pointer)类型

存储另一种类型的内存地址

/* 声明指针类型的语法 */
type* identifier;

char* cptr;

4、无(Void)类型

对定义函数的参数类型、返回值、函数中指针类型进行声明

public class Void Test{} // 无返回值
void* identifier; // 无类型指针:可以指向任何类型的数据

// void几乎只有“注释”和限制程序的作用,定义一个void变量没有意义

使用说明:

  1. 如果函数没有返回值,那么应声明为void类型
  2. 如果函数无参数,那么应声明其参数为void
  3. 小心使用void指针类型
  4. 如果函数的参数可以是任意类型指针,那么应声明其参数为void *
  5. void不能代表一个真实的变量

三、类型转换

  • 隐式类型转换:以安全方式进行转换,不会导致数据丢失
  • 显式类型转换:强制类型转换,需要强制转换运算符,并且会造成数据丢失
double d = 5673.74;
int i;
i = (int)d; // 强制转换 double 为 int,输出 5673
方法 描述
ToBoolean 如果可能的话,把类型转换为布尔型
ToByte 把类型转换为字节类型
ToChar 如果可能的话,把类型转换为单个 Unicode 字符类型
ToDateTime 把类型(整数或字符串类型)转换为 日期-时间 结构
ToDecimal 把浮点型或整数类型转换为十进制类型
ToDouble 把类型转换为双精度浮点型
ToInt16 把类型转换为 16 位整数类型
ToInt32 把类型转换为 32 位整数类型
ToInt64 把类型转换为 64 位整数类型
ToSbyte 把类型转换为有符号字节类型
ToSingle 把类型转换为小浮点数类型
ToString 把类型转换为字符串类型
ToType 把类型转换为指定类型
ToUInt16 把类型转换为 16 位无符号整数类型
ToUInt32 把类型转换为 32 位无符号整数类型
ToUInt64 把类型转换为 64 位无符号整数类型
int i = 75;
float f = 53.005f;
double d = 2345.7652;
bool b = true;

Console.WriteLine(i.ToString()); // 输出 "75"
Console.WriteLine(f.ToString()); // 输出 "53.005"
Console.WriteLine(d.ToString()); // 输出 "2345.7652"
Console.WriteLine(b.ToString()); // 输出 "True"

四、变量

变量只是一个供程序操作的存储区的名字;每个变量都有一个特定的类型,类型决定了变量的内存大小和布局;范围内的值可以存储在内存中,可以对变量进行一系列操作

类型 举例
整数类型 sbyte、byte、short、ushort、int、uint、long、ulong 和 char
浮点型 float 和 double
十进制类型 decimal
布尔类型 true 或 false 值,指定的值
空类型 可为空值的数据类型

1、变量定义

/* 变量定义的语法 */
<data_type> <variable_list>;

// data_type:一个有效的数据类型
// variable_list:由一个或多个用逗号分隔的标识符名称组成

int i, j, k;
char c, ch;
float f, salary;
double d;

2、变量初始化

/* 变量初始化的语法 */
variable_name = value;
<data_type> <variable_name> = value;

byte d = 3, f = 5;
double pi = 3.14159;
char x = 'x';

int num;
num = Convert.ToInt32(Console.ReadLine());

// ReadLine():接收来自用户的输入,并把它存储到一个变量中
// Convert.ToInt32():把用户输入的数据转换为 int 数据类型

3、两种表达式

  • lvalue 表达式:可以出现在赋值语句的左边或右边
  • rvalue 表达式:可以出现在赋值语句的右边,不能出现在赋值语句的左边

五、常量

常量是固定值,程序执行期间不会改变;常量可以是任何基本数据类型,可以被当作常规的变量,只是它们的值在定义后不能被修改

/* 定义常量的语法 */
const <data_type> <constant_name> = value;

const int c1 = 5;

1、整数常量

85 // 十进制
0213 // 八进制
0x4b // 十六进制
30 // 整型
30u // 无符号整型
30l // 长整型
30ul // 无符号长整型
前缀 含义
0x、0X 十六进制
0 八进制
(无) 十进制
后缀(可组合,不可重复) 含义
U、u unsigned(无符号)
L、l long(长)

2、浮点常量

3.14159 // 小数形式:必须包含小数点或指数,或同时包含两者
314159E-5L // 指数形式:必须包含整数或小数,或同时包含两者,有符号的指数用e或E表示

3、字符常量

'x' // 普通字符
'\t' // 转义序列
'\u02C0' // 通用字符
转义序列 含义
\\ \ 字符
\' ' 字符
\" " 字符
\? ? 字符
\a Alert 或 bell
\b 退格键(Backspace)
\f 换页符(Form feed)
\n 换行符(Newline)
\r 回车
\t 水平制表符 tab
\v 垂直制表符 tab
\ooo 一到三位的八进制数
\xhh . . . 一个或多个数字的十六进制数

4、字符串常量

string a = "hello, world"; // hello, world
string b = @"hello, world"; // hello, world
string c = "hello \t world"; // hello     world
string d = @"hello \t world"; // hello \t world
string e = "Joe said \"Hello\" to me"; // Joe said "Hello" to me
string f = @"Joe said ""Hello"" to me"; // Joe said "Hello" to me
string g = "\\\\server\\share\\file.txt"; // \\server\share\file.txt
string h = @"\\server\share\file.txt"; // \\server\share\file.txt
string i = "one\r\ntwo\r\nthree";
string j = @"one
two
three";

六、运算符

1、算术运算符

运算符 描述 实例( 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
int a = 1;
int b;

b = a++; // 先将a赋值给b,再对a进行自增运算:a → 2, b → 1
b = ++a; // 先将a进行自增运算,再将a赋值给b:a → 2, b → 2
b = a--; // 先将a赋值给b,再对a进行自减运算:a → 0, b → 1
b = --a; // 先将a进行自减运算,再将a赋值给b:a → 0, b → 0

2、关系运算符

运算符 描述 实例( A = 10, B = 20)
== 检查两个操作数的值是否相等,如果相等则条件为真 A == B → false
!= 检查两个操作数的值是否相等,如果不相等则条件为真 A != B → true
> 检查左操作数的值是否大于右操作数的值,如果是则条件为真 A > B → false
< 检查左操作数的值是否小于右操作数的值,如果是则条件为真 A < B → true
>= 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真 A >= B → false
<= 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真 A <= B → true

3、逻辑运算符

运算符 描述 实例( A = true, B = false)
&& 逻辑与运算符:如果两个操作数都非零,则条件为真 A && B → false
|| 逻辑或运算符:如果两个操作数中有任意一个非零,则条件为真。 A || B → true
! 逻辑非运算符:用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假 !(A && B) → true

4、位运算符

将条件值换算为二进制数后进行位运算,再将结果换算回去得出最终结果

运算符 描述 实例( A = 60, B = 13)
& 如果同时存在于两个操作数中,二进制 AND 运算符复制一位到结果中 A & B → 12(0000 1100)
| 如果存在于任一操作数中,二进制 OR 运算符复制一位到结果中 A | B → 61(0011 1101)
^ 如果存在于其中一个操作数中但不同时存在于两个操作数中,二进制异或运算符复制一位到结果中 A ^ B → 49(0011 0001)
~ 按位取反运算符是一元运算符,具有"翻转"位效果,即0变成1,1变成0,包括符号位 ~A → -61(1100 0011)
<< 二进制左移运算符。左操作数的值向左移动右操作数指定的位数 A << 2 → 240(1111 0000)
>> 二进制右移运算符。左操作数的值向右移动右操作数指定的位数 A >> 2 → 15(0000 1111)

5、赋值运算符

运算符 描述 实例
= 简单的赋值运算符,把右边操作数的值赋给左边操作数 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

6、其他运算符

运算符 描述 实例
sizeof() 返回数据类型的大小 sizeof(int)
typeof() 返回 class 的类型 typeof(StreamReader)
& 返回变量的地址 &a
* 变量的指针 *a
? : 条件表达式 c ? a : b
is 判断对象是否为某一类型 If(Ford is Car)
as 强制转换,即使转换失败也不会抛出异常 Object obj = new StringReader("Hello");
StringReader r = obj as StringReader;

运算符优先级:
() [] -> . ++ - -
+ - ! ~ ++ - - (type)* & sizeof()
* / %
+ -
<< >>
< <= > >=
== !=
&
^
|
&&
||
?:
= += -= *= /= %=>>= <<= &= ^= |=
,

七、判断

  • if 语句
if (boolean_expression)
{
   /* 如果布尔表达式为真将执行的语句 */
}
  • if…else 语句
if (boolean_expression)
{
   /* 如果布尔表达式为真将执行的语句 */
}
else
{
  /* 如果布尔表达式为假将执行的语句 */
}

// 条件运算符可替代 if...else 语句:
Exp1 ? Exp2 : Exp3;

// if...else if...else 语句:
if (boolean_expression 1)
{
   /* 当布尔表达式 1 为真时执行 */
}
else if (boolean_expression 2)
{
   /* 当布尔表达式 2 为真时执行 */
}
else if (boolean_expression 3)
{
   /* 当布尔表达式 3 为真时执行 */
}
else 
{
   /* 当上面条件都不为真时执行 */
}

// 另一种写法:
if (a == true)
    x = 1; // 若不书写花括号{},则默认只第一条语句由if执行
    y = 2; // 之后的语句则在if语句之后执行
    z = 3;
  • 嵌套 if 语句
if (boolean_expression 1)
{
   /* 当布尔表达式 1 为真时执行 */
   if (boolean_expression 2)
   {
      /* 当布尔表达式 2 为真时执行 */
   }
}
  • switch 语句
switch (expression){
    case constant-expression  :
       statement(s);
       break; 
    case constant-expression  :
       statement(s);
       break; 
  
    /* 您可以有任意数量的 case 语句 */
    default : /* 可选的 */
       statement(s);
       break; 
}

switch语句规则:

  1. expression 必须是一个整型或枚举类型,或者是一个 class 类型,其中 class 有一个单一的转换函数将其转换为整型或枚举类型。
  2. 在一个 switch 中可以有任意数量的 case 语句,每个 case 后跟一个要比较的值和一个冒号。
  3. case 的 constant-expression 必须与 switch 中的变量具有相同的数据类型,且必须是一个常量。
  4. 当被测试的变量等于 case 中的常量时,case 后跟的语句将被执行,直到遇到 break 语句时switch 终止,控制流将跳转到 switch 语句后的下一行。
  5. 如果 case 语句中有处理语句,则必须包含 break 或其他跳转语句;如果 case 语句为空,则可以不包含 break,控制流将会继续后续的 case,直到遇到 break 为止。
  6. 一个 switch 语句结尾可以有一个可选的 default case,用于在上面所有 case 都不为真时执行一个任务,default case 中的 break 语句不是必需的。
  7. C# 不支持从一个 case 标签显式贯穿到另一个 case 标签,如需要,可以使用 goto 一个 switch-case 或 goto default。
  • 嵌套 switch 语句
switch (ch1)
{
   case 'A':
      printf("这个 A 是外部 switch 的一部分" );
      switch (ch2)
      {
         case 'A':
            printf("这个 A 是内部 switch 的一部分" );
            break;
         case 'B': /* 内部 B case 代码 */
      }
      break;
   case 'B': /* 外部 B case 代码 */
}

八、循环

1、循环类型

  • while 循环
while (condition) // condition 可以是任意的表达式,当为任意非零值时都为真
{
   statement(s); // 可以是一个单独的语句,也可以是几个语句组成的代码块
}
  • for/foreach 循环
/* for 循环语法 */
for (init; condition; increment)
{
   statement(s);
}

/* foreach 循环语法 */
foreach (type objName in collection/Array)
{
   statement(s);
}

int[] fibarray = new int[] {0, 1, 1, 2, 3, 5, 8, 13};
foreach (int element in fibarray)
{
    System.Console.WriteLine(element);
}

for循环控制流:

  1. init 会首先被执行,且只会执行一次;允许声明并初始化任何循环控制变量,也可以只写一个分号。
  2. 判断 condition,如果为真则执行循环主体,如果为假则直接跳到紧接着 for 循环的下一条语句。
  3. 执行完 for 循环主体后,控制流会跳回 increment 语句,允许更新循环控制变量,也可以留空。
  4. 重复判断 condition,直到条件变为假时,循环终止。
  • do…while 循环
do
{
   statement(s);
} while (condition);

do…while循环控制流:

  1. 条件表达式出现在循环的尾部,所以循环中的 statement(s) 会在条件被测试之前至少执行一次。
  2. 如果 condition 为真,控制流会跳转回上面的 do,重新执行循环中的 statement(s)。
  3. 重复判断 condition,直到条件变为假时,循环终止。
  • 嵌套循环
/* 嵌套 for 循环语法 */
for (init; condition; increment)
{
   for (init; condition; increment)
   {
      statement(s);
   }
   statement(s);
}

/* 嵌套 while 循环语法 */
while (condition)
{
   while (condition)
   {
      statement(s);
   }
   statement(s);
}

/* 嵌套 do...while 循环语法 */
do
{
   statement(s);
   do
   {
      statement(s);
   } while (condition);

} while (condition);

2、循环控制语句

用于更改执行的正常序列,当执行离开一个范围时,所有在该范围中创建的自动对象都会被销毁

  • break 语句
循环 作用
switch break 用于终止一个 case
其他 break 会终止整个循环,且程序流将继续执行紧接着循环的下一条语句
int a = 10;
while (a < 20)
{
    a++;
    if (a > 15)
    {
        break; // a>15时终止while循环
    }
}
  • continue 语句
循环 作用
for continue 语句会导致执行条件测试和循环增量部分
while、do…while continue 语句会导致程序控制回到条件测试上
其他 continue 会跳过当前循环中的代码,强迫开始下一次循环
int a = 10;
do
{
    if (a == 15)
    {
        a = a + 1;
        continue; // a==15时跳过这次迭代,继续循环
    }
    a++;
} while (a < 20);

3、无限循环

如果条件永远不为假,则循环将变成无限循环

for (; ; ) // 当条件表达式不存在时,它被假设为真
{
    Console.WriteLine("陷入死循环啦!");
}

九、封装

把一个或多个项目封闭在一个物理的或者逻辑的包中,通过访问修饰符设置使用者的访问权限,防止对实现细节的访问

访问修饰符 访问权限
public 所有对象都可以访问
protected internal 访问限于当前程序集或派生自包含类的类型
internal 同一程序集内的对象可以访问
protected 只有该类对象及其子类对象可以访问
private 对象本身在对象内部可以访问

【学习笔记】C#基础 - 由C/C++衍生出来的面向对象的编程语言,学习笔记,c#,c语言,c++,学习笔记

1、Public 访问修饰符

允许一个类将其成员变量和成员函数暴露给所有函数和对象,当前程序集(项目)及外部程序集(项目)都可以访问

namespace RectangleApplication
{
    class Rectangle
    {
        public double length;
        public double width;
        public double GetArea()
        {
            return length * width;
        }
        public void Display()
        {
            Console.WriteLine("长度: {0}", length);
            Console.WriteLine("宽度: {0}", width);
            Console.WriteLine("面积: {0}", GetArea());
        }
        /* 成员变量及函数被声明为 public,故可被所有函数及类的实例访问 */
    }

    class ExecuteRectangle
    {
        static void Main(string[] args)
        {
            Rectangle r = new Rectangle();
            r.length = 4.5;
            r.width = 3.5;
            r.Display();
            Console.ReadLine();
        }
    }
}

2、Protected Internal 访问修饰符

允许在本类、派生类或者包含该类的程序集中访问,用于实现继承

3、Internal 访问修饰符

允许一个类将其成员变量和成员函数暴露给当前程序集中的其他函数和对象,外部程序集(项目)不可访问

namespace RectangleApplication
{
    class Rectangle
    {
        internal double length;
        internal double width;
        /* 成员变量被声明为 internal,故可被当前程序集的函数访问,不可被外部访问 */
        
        double GetArea() // 成员函数声明时不带有任何访问修饰符,默认为 private
        {
            return length * width;
        }
        public void Display()
        {
            Console.WriteLine("长度: {0}", length);
            Console.WriteLine("宽度: {0}", width);
            Console.WriteLine("面积: {0}", GetArea());
        }
    }
    
    class ExecuteRectangle
    {
        static void Main(string[] args)
        {
            Rectangle r = new Rectangle();
            r.length = 4.5;
            r.width = 3.5;
            r.Display();
            Console.ReadLine();
        }
    }
}

4、Protected 访问修饰符

允许子类访问它的基类的成员变量和成员函数,有助于实现继承

5、Private 访问修饰符

允许一个类将其成员变量和成员函数对其他的函数和对象进行隐藏,只有当前类的成员函数可以访问(类的实例不能访问)

namespace RectangleApplication
{
    class Rectangle
    {
        private double length;
        private double width;
        /* 成员变量被声明为 private,故可被当前类的成员函数访问,不可被类外访问 */
        
        public void Acceptdetails()
        {
            Console.WriteLine("请输入长度:");
            length = Convert.ToDouble(Console.ReadLine());
            Console.WriteLine("请输入宽度:");
            width = Convert.ToDouble(Console.ReadLine());
        }
        public double GetArea()
        {
            return length * width;
        }
        public void Display()
        {
            Console.WriteLine("长度: {0}", length);
            Console.WriteLine("宽度: {0}", width);
            Console.WriteLine("面积: {0}", GetArea());
        }
    }
    
    class ExecuteRectangle
    {
        static void Main(string[] args)
        {
            Rectangle r = new Rectangle();
            r.Acceptdetails();
            r.Display();
            Console.ReadLine();
        }
    }
}

注:如果类成员没有指定访问修饰符,则默认为 private

十、方法

1、定义及调用方法

/* 定义方法的语法 */
<Access Specifier> <Return Type> <Method Name>(Parameter List)
{
   Method Body
}

// Access Specifier:访问修饰符,声明变量或方法对于另一个类的可见性
// Return type:方法返回的值的数据类型,若无返回值则类型为 void
// Method name:方法名称,标识符唯一,且大小写敏感
// Parameter list:参数列表,用来传递和接收方法的数据
// Method body:方法主体,包含了完成任务所需的指令集

class NumberManipul
{
    /* 定义方法:访问修饰符 public,返回类型 int,方法名 FindMax,以及参数和主体 */
    public int FindMax(int num1, int num2)
    {
        int result;
        /* 若if内只执行一条语句,可以省略花括号{} */
        if (num1 > num2)
            result = num1;
        else
            result = num2;
            
        return result;
    }
    
    static void Main(string[] args)
    {
        int a = 100;
        int b = 200;
        int ret;
        NumberManipul n = new NumberManipul(); // 实例化 NumberManipul 类
        ret = n.FindMax(a, b); // 调用 FindMax 方法
        Console.WriteLine("最大值是: {0}", ret );
        Console.ReadLine();
    }
}

2、递归函数

一个方法可以自我调用,这就是所谓的递归

class NumberManipulator
{
    public int factorial(int num)
    {
        int result;
        if (num == 1)
        {
            return 1;
        }
        else
        {
            result = factorial(num - 1) * num; // 调用自身并迭代参数以实现递归
            return result;
        }
    }
    
    static void Main(string[] args)
    {
        NumberManipulator n = new NumberManipulator();
        Console.WriteLine("6 的阶乘是: {0}", n.factorial(6));
        Console.WriteLine("7 的阶乘是: {0}", n.factorial(7));
        Console.WriteLine("8 的阶乘是: {0}", n.factorial(8));
        Console.ReadLine();
    }
}

3、参数传递

  • 按值传递参数(默认方式)

当调用一个方法时,会为每个值参数创建一个新的存储位置;实际参数的值会复制给形参,实参和形参使用的是两个不同内存中的值,所以,当形参的值发生改变时,不会影响实参的值,从而保证了实参数据的安全

class NumberManipulator
{
    public void swap(int x, int y)
    {
        int temp;
        temp = x; // 保存 x 的值
        x = y; // 把 y 赋值给 x
        y = temp; // 把 temp 赋值给 y
    }
    
    static void Main(string[] args)
    {
        NumberManipulator n = new NumberManipulator();
        int a = 100;
        int b = 200;
        Console.WriteLine("在交换之前,a 的值: {0}", a);
        Console.WriteLine("在交换之前,b 的值: {0}", b);
        n.swap(a, b); // 调用函数来交换值
        Console.WriteLine("在交换之后,a 的值: {0}", a);
        Console.WriteLine("在交换之后,b 的值: {0}", b);
        Console.ReadLine();
    }
}

/* 结果表明,即使在函数内改变了值,值也没有发生任何的变化 */
  • 按引用传递参数

引用参数是一个对变量的内存位置的引用,它不会创建新的存储位置,而是与实际参数具有相同的内存位置,使用 ref 关键字声明引用参数

class NumberManipulator
{
    public void swap(ref int x, ref int y)
    {
        int temp;
        temp = x; // 保存 x 的值
        x = y; // 把 y 赋值给 x
        y = temp; // 把 temp 赋值给 y
    }
    
    static void Main(string[] args)
    {
        NumberManipulator n = new NumberManipulator();
        /* ref参数需在传递前初始化变量 */
        int a = 100;
        int b = 200;
        Console.WriteLine("在交换之前,a 的值: {0}", a);
        Console.WriteLine("在交换之前,b 的值: {0}", b);
        n.swap(ref a, ref b); // 调用函数来交换值
        Console.WriteLine("在交换之后,a 的值: {0}", a);
        Console.WriteLine("在交换之后,b 的值: {0}", b);
        Console.ReadLine();
    }
}

/* 结果表明,swap 函数内的值改变了,且这个改变可以在 Main 函数中反映出来 */
  • 按输出传递参数

输出参数也是一个对变量的内存位置的引用,它会把方法输出的数据赋给自己,可从函数中返回两个值,使用 out 关键字声明输出参数;提供给输出参数的变量不需要赋值,而当需要从一个未指定参数初始值的方法中返回值时,输出参数特别有用

class NumberManipulator
{
    public void getValues(out int x, out int y)
    {
        /* out参数需在函数内部初始化变量 */
        Console.WriteLine("请输入第一个值:");
        x = Convert.ToInt32(Console.ReadLine());
        Console.WriteLine("请输入第二个值:");
        y = Convert.ToInt32(Console.ReadLine());
    }
   
    static void Main(string[] args)
    {
        NumberManipulator n = new NumberManipulator();
        int a, b;
        n.getValues(out a, out b); // 调用函数来获取值
        Console.WriteLine("在方法调用之后,a 的值: {0}", a);
        Console.WriteLine("在方法调用之后,b 的值: {0}", b);
        Console.ReadLine();
    }
}

/* 获取的结果完全取决于用户输入 */

十一、可空类型(Nullable)

1、Nullable 类型定义?

表示其基础值类型正常范围内的值,再加上一个 null 值,用于对 int, double, bool 等数据类型进行 null 的赋值

/* 声明一个 nullable 类型的语法 */
<data_type>? <variable_name> = null;

class NullablesAtShow
{
    static void Main(string[] args)
    {
        int? num1 = null; // 输出空
        int? num2 = 45;
        double? num3 = new double?(); // 输出空
        double? num4 = 3.14157;
        bool? boolval = new bool?(); // 输出空
        Console.WriteLine("显示可空类型的值: {0}, {1}, {2}, {3}", num1, num2, num3, num4);
        Console.WriteLine("一个可空的布尔值: {0}", boolval);
        Console.ReadLine();
    }
}

2、Null 合并运算符??

用于定义可空类型和引用类型的默认值,为类型转换定义了一个预设值,以防可空类型的值为 Null;Null 合并运算符把操作数类型隐式转换为另一个可空(或不可空)的值类型的操作数的类型,如果第一个操作数的值为 null,则返回第二个操作数的值,否则返回第一个操作数的值

class NullablesAtShow
{
    static void Main(string[] args)
    {
        double? num1 = null;
        double? num2 = 3.14157;
        double num3;
        num3 = num1 ?? 5.34; // 若 num1 为空则返回 5.34,否则返回 num1 的值
        Console.WriteLine("num3 的值: {0}", num3);
        num3 = num2 ?? 5.34; // 若 num2 为空则返回 5.34,否则返回 num2 的值
        Console.WriteLine("num3 的值: {0}", num3);
        Console.ReadLine();
    }
}

十二、数组(Array)

1、数组基础

/* 声明一个数组的语法 */
datatype[] arrayName;

// datatype:指定被存储在数组中的元素的类型
// []:指定数组的秩(维度),秩指定数组的大小
// arrayName:指定数组的名称

double[] balance; // 声明数组
double[] balance = {2340.0, 4523.69, 3421.0}; // 声明并赋值给数组

double[] balance = new double[10]; // 初始化一个长度为10的数组(元素为默认值)
balance[0] = 4500.0; // 通过索引号赋值给单个元素

int[] marks = new int[5]  {99,  98, 92, 97, 95}; // 创建并初始化一个数组
int[] marks = new int[]  {99,  98, 92, 97, 95}; // 省略数组长度的写法
int[] score = marks; // 赋值一个数组变量到另一个数组变量中

2、数组细节

  • 多维数组

【学习笔记】C#基础 - 由C/C++衍生出来的面向对象的编程语言,学习笔记,c#,c语言,c++,学习笔记

string [,] names; // 声明一个 string 变量的二维数组
int [,,] m; // 声明一个 int 变量的三维数组

(未完待续)文章来源地址https://www.toymoban.com/news/detail-733081.html

到了这里,关于【学习笔记】C#基础 - 由C/C++衍生出来的面向对象的编程语言的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C#基础】C# 面向对象编程

    序号 系列文章 5 【C#基础】C# 运算符总结 6 【C#基础】C# 常用语句讲解 7 【C#基础】C# 常用数据结构 😊大家好,我是writer桑,前面一章已经学习了 C# 中的常用数据结构,那本章就开始学习 C# 程序中面向对象编程的知识,希望看完大家能够有所收获,感谢支持! 面向对象编程

    2024年02月04日
    浏览(54)
  • C#核心学习(面向对象)

    基本概念: 在实例化对象时,会调用的用于初始化的函数,如果不写,则默认存在一个无参构造函数。 写法: 1、没有返回值 2、函数名和类名必须相同 3、没有特殊需求时,一般是 public 4、构造函数可以被重载 5、this代表当前调用该函数的对象自己 特殊写法 可以通过this 重

    2024年02月03日
    浏览(40)
  • 【Java语言面向对象】(1)面向过程编程

    人机猜拳的第一版(下方是程序源码) 人机猜拳(面向过程版本) 三部分组成 初始化 游戏开始 游戏数据统计 逐步完成,并阶段测试。 面向过程整体的思路:做一件事,分为多个步骤,每个步骤之间是有序的,最后按序完成。 面向过程的优缺点: 优点:符合人类思维,简

    2023年04月09日
    浏览(54)
  • Go语言面向对象编程

    注:安装教程 上一篇 1.1、简单实例 1.2、指针 1、Go语言中的面向对象最为直观,也无需支付额外的成本。如果要求对象必须以指针传递,这有时会是个额外成本,因为对象有时很小(比如4字节),用指针传递并不划算。 只有在你需要修改对象的时候,才必须用指针。它不是

    2024年02月06日
    浏览(56)
  • 【转载】R语言 面向对象编程

    转载自:R语言教程 面向对象的编程侧重于数据和对象,而不是程序。面向对象的模型有助于我们对现实生活中的对象进行建模。为了在数据科学领域出类拔萃,掌握面向对象的编程概念很重要。每个程序都有特殊类型的类。在本教程中,将重点讨论R语言中的S3和S4类、泛型函

    2024年01月20日
    浏览(117)
  • 【JAVA】面向对象的编程语言(继承篇)

    个人主页:【😊个人主页】 系列专栏:【❤️初识JAVA】 在之前的文章中,我们介绍过面向对象的编程语言,今天我们就来就进入到JAVA面对对象的编程世界,今天我们主要来介绍面向对象的编程范式中一个重要的概念——继承。 继承是java面向对象编程技术的一块基石,因为

    2024年02月09日
    浏览(45)
  • Rust编程语言入门之Rust的面向对象编程特性

    Rust 受到多种编程范式的影响,包括面向对象 面向对象通常包含以下特性:命名对象、封装、继承 “设计模式四人帮”在《设计模型》中给面向对象的定义: 面向对象的程序由对象组成 对象包装了数据和操作这些数据的过程,这些过程通常被称作方法或操作 基于此定义:

    2023年04月21日
    浏览(54)
  • 【深入浅出C#】章节 4: 面向对象编程基础:封装、继承和多态

    封装、继承和多态是面向对象编程中的核心概念,它们对于构建灵活、可扩展和可维护的软件系统至关重要。 封装(Encapsulation)通过将数据和相关操作封装在一个类中,隐藏内部实现细节,并提供公共接口来与外部进行交互。封装有助于保护数据的完整性和安全性,同时提

    2024年02月10日
    浏览(58)
  • 【跟小嘉学 Rust 编程】十七、面向对象语言特性

    【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学 Rust 编程】六、枚举

    2024年02月10日
    浏览(89)
  • 学习笔记整理-面向对象-01-认识对象

    1. 对象 对象(object)是 键值对 的集合,表示属性和值的 映射关系 。 对象的语法 k和v之间用冒号分割,每组 k:v 之间用逗号分割,最后一个 k:v 对后可以不书写逗号。 属性是否加引号 如果对象的属性键名不符合命名规范,则这个键名必须用引号包裹。 属性的访问 可以用 点语

    2024年02月13日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包