C#入门篇7(面向对象)

目录

一、值传递和引用传递

1、概念

2、主要区别

3、用法

 二、字符串

1、字符串的不可变性可以将字符串看作只读字符数组

2、字符串提供的各种方法

 三、继承

1、 概念

2、格式

3、示例

4、子类继承于父类什么?

5、继承的特性

6、查看类图

四、new关键字

1、概念

2、使用 new 关键字隐藏父类成员

3、如何访问隐藏的成员

4、 隐式和显式成员隐藏


一、值传递和引用传递

值类型引用类型是两种基本的数据类型,它们在内存管理、存储方式以及行为上有明显的区别。以下是它们的定义、主要区别、用法示例以及相关概念的详细说明。

1、概念
  • 值类型(Value Types):

    • 值类型直接存储数据本身。
    • 主要包括基本数据类型,如 intfloatcharbool,以及结构体(struct)和枚举(enum)。
    • 当值类型的变量被赋值给另一个变量时,实际的值会被复制。
  • 引用类型(Reference Types):

    • 引用类型存储的是数据的引用(地址),而不是数据本身。
    • 主要包括类(class)、接口(interface)、数组(array)和字符串(string)。
    • 当引用类型的变量被赋值给另一个变量时,赋值的是引用(地址),因此它们指向同一块内存。
2、主要区别
特性 值类型 引用类型
存储方式 存储在栈中 存储在堆中
赋值方式 赋值时复制实际值 赋值时复制引用(地址)
默认值 有默认值(如 0false'\0' 等) 默认值为 null
继承支持 不支持继承 支持继承
适用场景 适用于小的数据量和简单类型(如基本类型、结构体等) 适用于复杂的数据结构(如对象、数组等)
3、用法
值类型示例
using System;

public class ValueTypeExample
{
    public static void Main()
    {
        int a = 10; // 值类型
        int b = a;  // 复制 a 的值
        b = 20;     // 修改 b 的值

        Console.WriteLine("a: " + a); // 输出: a: 10
        Console.WriteLine("b: " + b); // 输出: b: 20
    }
}
解释:

在这个示例中,int 是一个值类型。b 被赋值为 a 的值,因此当 b 的值被修改时,a 的值并没有改变。
using System;

public class ReferenceTypeExample
{
    public class Person // 引用类型
    {
        public string Name { get; set; }
    }

    public static void Main()
    {
        Person person1 = new Person { Name = "Alice" }; // 创建对象
        Person person2 = person1; // 赋值引用

        person2.Name = "Bob"; // 修改 person2 的属性

        Console.WriteLine("person1.Name: " + person1.Name); // 输出: person1.Name: Bob
        Console.WriteLine("person2.Name: " + person2.Name); // 输出: person2.Name: Bob
    }
}
解释:

在这个示例中,Person 是一个引用类型。person2 被赋值为 person1 的引用,因此它们指向同一个 Person 对象。当通过 person2 修改 Name 属性时,person1 的 Name 也随之改变。

 二、字符串

1、字符串的不可变性可以将字符串看作只读字符数组
string s = "abcdef" ;

//s[0] = 'b';//不能这样做,因为只读

//首先将字符串转换为char类型的数组

char[] chs = s.ToCharArray();

chs[0] = 'b' ;
//将字符数组转换为我们的字符串

s= new string(chs);
//既然可以将string看作char类型的制度数组,所以我可以通过下表去访问字符串中的某一个元素
Console.WriteLine(s[0]);
Console.WriteLine(s);
Console.ReadKey();

1、ToCharArray() ;将字符串转换成char数组

2、new string(char[] cha);能够将char数组转换为字符串

3、StringBuilder 的使用

2、字符串提供的各种方法

1、length:获得当前字符串的长度

2、ToUpper:将字符串转换成大写

3、ToLower:将字符串转换成小写

4、str.Equals:比较字符串是否相等

5、StringComparison.OrdinalIgnoreCase:忽略被比较字符串的大小写

6、split :分割字符串,返回字符串类型的数组

7、contains:判断目标字符是否存在

8、raplace:替换目标字符

9、substring:截取字符串

10、startwith:判断这个字符串以什么开头

11、endwith:判断这个字符串以什么结尾

12、indexof:搜索目标字符的位置

13、lastindex:搜索最后一个目标字符的位置

14、trim:移除字符串两端的空白字符

15、isnullorempty:判断字符串是否为空

16、join:将字符串数组连接成一个字符串,使用逗号作为分隔符

using System;

public class StringManipulationExample
{
    public static void Main()
    {
        // 初始化两个字符串
        string str1 = "Hello, World!";
        string str2 = "hello, world!";

        // 1. 使用 Length 属性获取字符串长度
        int lengthStr1 = str1.Length;
        Console.WriteLine("Length of str1: " + lengthStr1); // 输出: Length of str1: 13

        // 2. 使用 ToUpper 方法将字符串转换为大写
        string upperStr1 = str1.ToUpper();
        Console.WriteLine("Uppercase str1: " + upperStr1); // 输出: Uppercase str1: HELLO, WORLD!

        // 3. 使用 ToLower 方法将字符串转换为小写
        string lowerStr1 = str1.ToLower();
        Console.WriteLine("Lowercase str1: " + lowerStr1); // 输出: Lowercase str1: hello, world!

        // 4. 使用 Equals 方法比较字符串是否相等
        bool areEqual = str1.Equals(str2);
        Console.WriteLine("str1 equals str2 (case-sensitive): " + areEqual); // 输出: str1 equals str2 (case-sensitive): False

        // 5. 使用 StringComparison.OrdinalIgnoreCase 忽略大小写比较字符串
        bool areEqualIgnoreCase = str1.Equals(str2, StringComparison.OrdinalIgnoreCase);
        Console.WriteLine("str1 equals str2 (case-insensitive): " + areEqualIgnoreCase); // 输出: str1 equals str2 (case-insensitive): True
    }
}
using System;

public class DateSplitExample
{
    public static void Main()
    {
        // 示例日期字符串
        string dateStr = "2024-08-28";

        // 使用 Split 方法分割字符串,指定分隔符为连字符 '-'
        string[] dateParts = dateStr.Split('-');

        // 输出分割后的结果
        Console.WriteLine("Year: " + dateParts[0]);  // 输出: Year: 2024
        Console.WriteLine("Month: " + dateParts[1]); // 输出: Month: 08
        Console.WriteLine("Day: " + dateParts[2]);   // 输出: Day: 28
    }
}
using System;

public class StringOperationsExample
{
    public static void Main()
    {
        // 示例字符串
        string sentence = "The quick brown fox jumps over the lazy dog.";

        // 7. 使用 Contains 方法检查目标字符串是否存在
        string wordToFind = "fox";
        bool containsWord = sentence.Contains(wordToFind);
        Console.WriteLine($"Contains '{wordToFind}': {containsWord}"); // 输出: Contains 'fox': True

        // 8. 使用 Replace 方法替换目标字符串
        string wordToReplace = "dog";
        string replacementWord = "cat";
        string newSentence = sentence.Replace(wordToReplace, replacementWord);
        Console.WriteLine("After Replace: " + newSentence); // 输出: After Replace: The quick brown fox jumps over the lazy cat.

        // 9. 使用 Substring 方法截取字符串
        int startIndex = 4;
        int length = 5;
        string substring = sentence.Substring(startIndex, length);
        Console.WriteLine("Substring: " + substring); // 输出: Substring: quick
    }
}
using System;

public class StringMethodsExample
{
    public static void Main()
    {
        // 示例字符串
        string sentence = "The quick brown fox jumps over the lazy dog.";

        // 10. 使用 StartsWith 判断字符串是否以某个子字符串开头
        string startWord = "The";
        bool startsWith = sentence.StartsWith(startWord);
        Console.WriteLine($"Starts with '{startWord}': {startsWith}"); // 输出: Starts with 'The': True

        // 11. 使用 EndsWith 判断字符串是否以某个子字符串结尾
        string endWord = "dog.";
        bool endsWith = sentence.EndsWith(endWord);
        Console.WriteLine($"Ends with '{endWord}': {endsWith}"); // 输出: Ends with 'dog.': True

        // 12. 使用 IndexOf 查找目标字符的位置
        char targetChar = 'f';
        int indexOfChar = sentence.IndexOf(targetChar);
        Console.WriteLine($"Index of '{targetChar}': {indexOfChar}"); // 输出: Index of 'f': 16

        // 13. 使用 LastIndexOf 查找最后一个目标字符的位置
        int lastIndexOfChar = sentence.LastIndexOf(targetChar);
        Console.WriteLine($"Last index of '{targetChar}': {lastIndexOfChar}"); // 输出: Last index of 'f': 16
    }
}
using System;
using System.Linq;

public class StringMethodsDemo
{
    public static void Main()
    {
        // 14. Trim: 移除字符串两端的空白字符
        string originalString = "   Hello, World!   ";
        string trimmedString = originalString.Trim();
        Console.WriteLine("Original: '" + originalString + "'"); // 输出带空格的原始字符串
        Console.WriteLine("Trimmed: '" + trimmedString + "'"); // 输出移除了空格的字符串

        // 15. IsNullOrEmpty: 判断字符串是否为空或为null
        string emptyString = "";
        bool isEmpty1 = string.IsNullOrEmpty(emptyString);
        Console.WriteLine("Is '" + emptyString + "' null or empty? " + isEmpty1); // 输出: True

        string nullString = null;
        bool isEmpty2 = string.IsNullOrEmpty(nullString);
        Console.WriteLine("Is nullString null or empty? " + isEmpty2); // 输出: True

        // 16. Join: 将字符串数组连接成一个字符串,使用逗号作为分隔符
        string[] words = { "apple", "banana", "cherry" };
        string joinedString = string.Join(", ", words);
        Console.WriteLine("Joined string: " + joinedString); // 输出: apple, banana, cherry
    }
}

 三、继承

解决代码冗余,将重复成员封装成一个类,作为一些类的父类

C#入门篇7(面向对象)_第1张图片

1、 概念

创建一个新类(子类或派生类),这个新类继承自一个已有的类(基类或父类)。继承允许子类自动获取父类的属性和方法,从而实现代码的重用和扩展。

2、格式
//父类
public class BaseClass
{
    // 字段
    public int Field;

    // 属性
    public string Property { get; set; }

    // 方法
    public void Method()
    {
        // 方法实现
    }

    // 带有 virtual 修饰符的方法,允许在派生类中重写
    public virtual void VirtualMethod()
    {
        // 方法实现
    }
}
//子类
public class DerivedClass : BaseClass
{
    // 新增字段
    public int AdditionalField;

    // 新增属性
    public string AdditionalProperty { get; set; }

    // 新增方法
    public void NewMethod()
    {
        // 方法实现
    }

    // 重写基类的虚方法
    public override void VirtualMethod()
    {
        // 重写方法实现
        // 可以调用基类的方法
        base.VirtualMethod();
    }
}
3、示例
class Program
{
    static void Main(string[] args)
    {
        // 创建派生类的实例
        DerivedClass derived = new DerivedClass();

        // 访问基类成员
        derived.Field = 10;
        derived.Property = "Base Property";
        derived.Method();

        // 访问派生类成员
        derived.AdditionalField = 20;
        derived.AdditionalProperty = "Derived Property";
        derived.NewMethod();

        // 调用重写的方法
        derived.VirtualMethod();
    }
}
4、子类继承于父类什么?
  • 属性:子类继承父类的所有公共(public)和保护(protected)属性。属性是类中用于存储数据的成员变量。子类可以访问和修改这些继承的属性。

  • 方法:子类继承父类的所有公共和保护方法。这些方法可以直接在子类中使用,或者在子类中进行重写(如果父类的方法是 virtual 或 abstract)。

  •  事件:子类继承父类定义的公共和保护事件。事件通常用于通知订阅者某些操作的发生。

  • .索引器:子类继承父类定义的索引器。索引器允许类的实例像数组一样使用索引进行访问

  • 构造函数:构造函数不会被继承。子类必须定义自己的构造函数,并可以通过 base 关键字调用父类的构造函数以初始化父类的成员

  • 访问修饰符:子类可以访问父类的公共(public)和保护(protected)成员,但不能访问父类的私有(private)成员。私有成员仅在定义它的类内部可见。

  • 内部类和静态成员:如果父类定义了内部类或静态成员,子类也可以访问这些静态成员,但内部类的访问权限取决于其定义的位置和访问修饰符。

5、继承的特性
  • 继承的单根性:一个子类只能有一个父类
  • 继承的传递性:它指的是如果一个类A继承了类B,并且类B又继承了类C,那么类A也隐含地继承了类C的属性和方法
6、查看类图
  • 在 Visual Studio 2022 中,点击菜单栏上的 “视图”(View)。

    • 从下拉菜单中选择 “类视图”(Class View)。你也可以通过快捷键 Ctrl+Shift+C 打开类视图。

四、new关键字

1、概念

使用 new 关键字可以在子类中隐藏父类的成员。这种隐藏机制允许你在子类中重新定义与父类中同名的成员(属性、方法、字段等),而不是继承和重用父类的成员。需要注意的是,使用 new 关键字隐藏成员不会改变父类成员的行为,仅仅是在子类中定义了一个新的成员。

2、使用 new 关键字隐藏父类成员

当你在子类中使用 new 关键字声明一个与父类中成员同名的新成员时,子类中的成员将隐藏父类中的成员。这种情况下,父类中的成员在子类对象中将被隐藏,但仍然存在于父类的上下文中。

public class Animal
{
    public void Speak()
    {
        Console.WriteLine("Animal speaks");
    }
}

public class Dog : Animal
{
    // 使用 new 关键字隐藏父类中的 Speak 方法
    public new void Speak()
    {
        Console.WriteLine("Dog barks");
    }
}
3、如何访问隐藏的成员

当你通过父类的引用访问子类对象时,调用的是父类中定义的成员,而不是子类中隐藏的成员。

public class Program
{
    public static void Main()
    {
        Dog myDog = new Dog();

        // 使用 Dog 类型调用 Speak 方法
        myDog.Speak(); // 输出: Dog barks

        // 使用 Animal 类型调用 Speak 方法
        Animal myAnimal = myDog;
        myAnimal.Speak(); // 输出: Animal speaks
    }
}
4、 隐式和显式成员隐藏

  • 隐式隐藏:当你仅使用 new 关键字时,编译器不会产生警告。子类中的成员会隐藏父类中的同名成员,但这可能导致代码的可读性和维护性问题,因为开发者可能不清楚隐藏的行为。

  • 显式隐藏:你可以使用 new 关键字显式地隐藏父类成员,并建议开发者注意这一点。显式隐藏可以提高代码的明确性。

你可能感兴趣的:(c#,开发语言,c#入门)