菜鳥的C#學習(二)

文章目錄

  • 一、類的訪問
    • 1、普通類繼承抽象類
    • 2、普通類繼承抽象類,抽象類繼承接口,三者聯系
  • 二、類中方法的訪問
    • 2.1 抽象方法和虛方法
    • 2.2 虛方法和普通方法
      • **1. 調用機制**
      • **2. 方法重寫**
      • **3. 設計意圖**
      • **4. 性能差異**
      • **5. 語法對比表**
      • **總結:何時使用?**
  • 三、迭代器的使用
    • 3.1、使用場景及示例
    • 3.2、
  • 四、深度復制與淺度復制
    • 4.1、解析及示例
      • 1. **淺度復制(Shallow Copy)**
      • 2. **深度復制(Deep Copy)**
  • 五、引用和值類型
      • 一、值類型(Value Types)
      • 二、引用類型(Reference Types)

一、類的訪問

在這里插入圖片描述

1、普通類繼承抽象類

在C#里,普通類繼承抽象類時,有以下這些要點需要留意:

1. 必須實現所有抽象成員
抽象類中的抽象方法和屬性不具備實現代碼,繼承它的普通類得把這些抽象成員全部實現出來。實現時,方法簽名要和抽象類中定義的保持一致,并且要用override關鍵字。

public abstract class Shape
{public abstract double Area(); // 抽象方法
}public class Circle : Shape
{public double Radius { get; set; }// 實現抽象方法public override double Area() => Math.PI * Radius * Radius;
}

2. 遵循訪問修飾符的限制
在實現抽象成員時,訪問修飾符要和抽象類中定義的一樣。比如,抽象類里的抽象方法是protected,那么派生類中實現該方法時也得用protected

3. 不能直接實例化抽象類
抽象類沒辦法直接創建實例,必須通過派生類來實例化。

Shape shape = new Circle { Radius = 5 }; // 正確
Shape shape = new Shape(); // 錯誤,無法實例化抽象類

4. 可以添加新成員
繼承抽象類的普通類能夠新增自己的字段、屬性、方法或者事件。

public class Rectangle : Shape
{public double Width { get; set; }public double Height { get; set; }public override double Area() => Width * Height;// 新增方法public double Perimeter() => 2 * (Width + Height);
}

5. 抽象類可以包含非抽象成員
抽象類中除了抽象成員,還能有已經實現的方法、屬性等,派生類可以直接繼承或者重寫這些非抽象成員。

public abstract class Animal
{public string Name { get; set; }public void Eat() => Console.WriteLine($"{Name} is eating."); // 非抽象方法public abstract void MakeSound(); // 抽象方法
}public class Dog : Animal
{public override void MakeSound() => Console.WriteLine("Woof!");
}

6. 抽象類也能繼承自其他類或抽象類
如果抽象類繼承了另一個抽象類,它可以選擇實現部分抽象成員,剩下的由派生類去實現。

public abstract class Vehicle
{public abstract void Start();
}public abstract class Car : Vehicle
{public override void Start() => Console.WriteLine("Car started."); // 實現基類的抽象方法public abstract void Drive(); // 定義新的抽象方法
}public class SportsCar : Car
{public override void Drive() => Console.WriteLine("Sports car is driving fast.");
}

7. 不能用 sealed 修飾派生類
因為普通類要實現抽象類的抽象成員,所以不能用sealed關鍵字修飾該普通類,不然就沒辦法被其他類繼承了。

總結
普通類繼承抽象類時,要實現所有抽象成員,遵循訪問修飾符的規則,不能實例化抽象類,不過可以添加新成員。抽象類可以有非抽象成員,還能繼承其他類或抽象類。

2、普通類繼承抽象類,抽象類繼承接口,三者聯系

當一個類(派生類)繼承抽象基類,而抽象基類又實現了接口時,三者的成員函數關系遵循以下規則(以C#為例):

1. 接口定義“契約”,抽象基類部分或全部實現,派生類完成剩余實現

  • 接口:定義必須實現的成員(如方法、屬性),但不提供實現。
  • 抽象基類
    • 必須“聲明”實現接口的所有成員(即使只實現部分)。
    • 可將部分接口成員標記為 abstract(延遲到派生類實現),其他成員提供具體實現。
  • 派生類
    • 必須實現抽象基類中標記為 abstract 的接口成員(若有)。
    • 可選擇重寫(override)抽象基類中已實現的接口成員(若為 virtual)。

2. 示例說明
假設存在以下結構:

// 接口定義
public interface IMyInterface
{void MethodA();  // 接口方法void MethodB();
}// 抽象基類實現接口
public abstract class MyAbstractBase : IMyInterface
{public void MethodA()  // 具體實現接口方法{Console.WriteLine("Base.MethodA");}public abstract void MethodB();  // 抽象方法,延遲到派生類實現
}// 派生類繼承抽象基類
public class MyDerivedClass : MyAbstractBase
{public override void MethodB()  // 實現抽象基類的抽象方法{Console.WriteLine("Derived.MethodB");}
}

成員關系分析

  • 接口 IMyInterface:定義 MethodA()MethodB()
  • 抽象基類 MyAbstractBase
    • 實現 MethodA(),派生類可直接使用。
    • MethodB() 標記為 abstract,強制派生類實現。
  • 派生類 MyDerivedClass
    • 無需關心 MethodA()(已由基類實現)。
    • 必須實現 MethodB(),否則會編譯錯誤。

3. 特殊情況:抽象基類未完全實現接口
若抽象基類未實現接口的所有成員(即部分接口成員未被標記為 abstract 且未提供實現),則會導致編譯錯誤。例如:

public abstract class MyAbstractBase : IMyInterface
{// 錯誤:未實現 MethodB(),且未聲明為 abstractpublic void MethodA() { }
}

修正方式

  • MethodB() 聲明為 abstract(如示例所示)。
  • 或在抽象基類中提供 MethodB() 的具體實現。

4. 接口顯式實現與隱式實現
抽象基類可選擇顯式實現接口(只能通過接口類型調用):

public abstract class MyAbstractBase : IMyInterface
{void IMyInterface.MethodA()  // 顯式實現接口方法{Console.WriteLine("Explicit implementation");}public abstract void MethodB();
}

此時,派生類需通過接口類型調用 MethodA()

MyDerivedClass derived = new MyDerivedClass();
((IMyInterface)derived).MethodA();  // 必須轉型為接口類型

5. 派生類重寫基類的實現
若抽象基類的方法為 virtual,派生類可選擇重寫:

public abstract class MyAbstractBase : IMyInterface
{public virtual void MethodA() { }  // 虛擬方法public abstract void MethodB();
}public class MyDerivedClass : MyAbstractBase
{public override void MethodA() { }  // 重寫基類方法public override void MethodB() { }  // 實現抽象方法
}

6. 多層繼承的擴展
若存在多層繼承(如抽象基類繼承自另一個抽象基類),規則相同:

  • 每個抽象基類可實現部分接口成員,剩余抽象成員由最終派生類實現。
  • 示例:
    public interface IMyInterface { void MethodA(); }
    public abstract class Base1 : IMyInterface { public abstract void MethodA(); }
    public abstract class Base2 : Base1 { }  // 未實現 MethodA(),仍為抽象類
    public class Derived : Base2 { public override void MethodA() { } }  // 最終實現
    

總結

角色對接口成員的責任對抽象成員的責任
接口定義所有成員簽名
抽象基類必須聲明實現所有接口成員(部分或全部實現)可定義抽象成員,強制派生類實現
派生類實現抽象基類中未實現的接口成員(即抽象成員)必須實現基類的所有抽象成員

這種分層設計允許:

  • 接口 定義統一契約。
  • 抽象基類 復用通用邏輯,簡化派生類實現。
  • 派生類 專注于核心差異化邏輯。

二、類中方法的訪問

在這里插入圖片描述

2.1 抽象方法和虛方法

在C#中,抽象方法虛方法都用于實現多態性,但它們的設計目的和使用方式有本質區別。以下是兩者的核心差異:

1. 定義語法與強制實現

抽象方法虛方法
使用 abstract 關鍵字聲明,且不能有方法體
csharp<br>public abstract void Print();<br>
使用 virtual 關鍵字聲明,必須有默認實現
csharp<br>public virtual void Print() { Console.WriteLine("Base"); }<br>
必須由派生類實現,否則派生類必須聲明為抽象類。派生類可以選擇是否重寫,不重寫時將繼承基類的默認實現。

2. 所在類的限制

  • 抽象方法:只能存在于抽象類中(即使用 abstract 修飾的類)。
  • 虛方法:可以存在于普通類抽象類中。

3. 重寫要求

抽象方法虛方法
派生類必須使用 override 關鍵字實現,且不能使用 newsealed 隱藏基類方法派生類使用 override 關鍵字重寫(推薦),或使用 new 關鍵字隱藏基類方法(不推薦)。
示例:
csharp<br>public override void Print() { ... }<br>
示例:
csharp<br>public override void Print() { ... } // 重寫<br>public new void Print() { ... } // 隱藏(不推薦)<br>

4. 設計目的

  • 抽象方法:用于定義必須由子類實現的契約,基類只規定方法簽名,不提供默認行為。例如:
    public abstract class Shape
    {public abstract double Area(); // 所有形狀必須計算面積
    }
    
  • 虛方法:用于提供可擴展的默認行為,允許子類在需要時修改實現。例如:
    public class Animal
    {public virtual void Speak() { Console.WriteLine("Animal sound"); }
    }public class Dog : Animal
    {public override void Speak() { Console.WriteLine("Woof"); } // 可選重寫
    }
    

5. 調用方式

  • 抽象方法:無法直接調用,必須通過派生類的實現調用。
  • 虛方法:可以直接通過基類調用默認實現,也可以通過派生類調用重寫后的實現。

總結對比表

特性抽象方法虛方法
方法體不能有方法體必須有默認實現
所在類必須在抽象類中可以在普通類或抽象類中
強制實現派生類必須實現派生類可選重寫
關鍵字abstract + overridevirtual + override(可選)
設計意圖定義必須實現的契約提供可擴展的默認行為

示例代碼

// 抽象類 + 抽象方法
public abstract class Vehicle
{public abstract void Start(); // 必須由子類實現
}// 普通類 + 虛方法
public class Car : Vehicle
{public override void Start() { Console.WriteLine("Car started"); } // 實現抽象方法public virtual void Drive() { Console.WriteLine("Driving normally"); } // 虛方法,提供默認行為
}// 派生類重寫虛方法
public class SportsCar : Car
{public override void Drive() { Console.WriteLine("Driving fast!"); } // 重寫虛方法
}

何時使用?

  • 使用抽象方法:當基類無法提供有意義的默認實現,且所有子類必須強制實現某個行為時。
  • 使用虛方法:當基類可以提供默認行為,但子類可能需要自定義實現時。

通過合理使用抽象方法和虛方法,可以構建出靈活且易于擴展的面向對象系統。

2.2 虛方法和普通方法

在C#中,虛方法virtual)和普通方法(無修飾符)的核心區別在于是否支持運行時多態。以下是兩者的詳細對比:

1. 調用機制

虛方法普通方法
使用 virtual 關鍵字聲明,支持運行時多態。基類的虛方法可以在派生類中被override重寫。調用時,會根據對象的實際類型決定執行哪個版本的方法。沒有特殊修飾符,不支持運行時多態。調用時,根據對象的聲明類型決定執行的方法,無論對象的實際類型是什么。
示例
csharp<br>public class Animal {<br> public virtual void Speak() { Console.WriteLine("Animal"); }<br>}<br><br>public class Dog : Animal {<br> public override void Speak() { Console.WriteLine("Dog"); }<br>}<br><br>// 輸出:Dog<br>Animal animal = new Dog();<br>animal.Speak(); // 調用Dog的實現<br>
示例
csharp<br>public class Animal {<br> public void Speak() { Console.WriteLine("Animal"); }<br>}<br><br>public class Dog : Animal {<br> public new void Speak() { Console.WriteLine("Dog"); } // 使用new隱藏基類方法(不推薦)<br>}<br><br>// 輸出:Animal<br>Animal animal = new Dog();<br>animal.Speak(); // 調用Animal的實現<br>

2. 方法重寫

虛方法普通方法
可以被派生類使用 override 關鍵字重寫,從而改變方法的行為。不能被重寫,但可以使用 new 關鍵字隱藏基類方法(但這不是真正的重寫,只是創建了一個同名的新方法)。
正確做法
csharp<br>public class Base {<br> public virtual void Print() { ... }<br>}<br><br>public class Derived : Base {<br> public override void Print() { ... } // 重寫虛方法<br>}<br>
錯誤做法(隱藏而非重寫):
csharp<br>public class Base {<br> public void Print() { ... }<br>}<br><br>public class Derived : Base {<br> public new void Print() { ... } // 隱藏基類方法(編譯警告)<br>}<br>

3. 設計意圖

虛方法普通方法
用于實現多態性,允許基類定義通用行為,派生類根據需要自定義實現。例如:
csharp<br>public class Shape {<br> public virtual double Area() => 0;<br>}<br><br>public class Circle : Shape {<br> public override double Area() => Math.PI * Radius * Radius;<br>}<br>
用于實現固定行為,不希望派生類修改方法邏輯。例如:
csharp<br>public class Calculator {<br> public int Add(int a, int b) => a + b; // 不需要重寫的方法<br>}<br>

4. 性能差異

  • 虛方法:調用時需要通過虛函數表(VTable)動態查找實際要執行的方法,因此性能略低(但在大多數場景下可以忽略不計)。
  • 普通方法:調用時直接綁定到聲明類型的方法,性能更高

5. 語法對比表

特性虛方法普通方法
關鍵字virtual
能否重寫能(使用 override不能(只能用 new 隱藏)
多態支持運行時多態(根據對象實際類型)編譯時綁定(根據聲明類型)
默認行為基類提供默認實現,可被覆蓋行為固定,不可被派生類修改
性能略低(通過VTable查找)更高(直接調用)

總結:何時使用?

  • 使用虛方法
    • 當基類希望派生類能夠自定義某個方法的實現時。
    • 需要通過基類引用調用派生類方法(實現多態)。
  • 使用普通方法
    • 當方法的邏輯不需要被派生類修改時。
    • 性能敏感的場景(如高頻調用的方法)。

通過合理使用虛方法和普通方法,可以在保證代碼靈活性的同時,避免不必要的性能開銷。

三、迭代器的使用

3.1、使用場景及示例

在這里插入圖片描述

在迭代塊中,使用yield關鍵字選擇要在foreach循環中使用的值,其語法如下

yield return <value>;

  • 迭代一個類成員(比如方法)IEnumerable
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace SimpleIterators
{class Program{public static IEnumerable SimpleList(){yield return "string 1";yield return "string 2";yield return "string 3";}static void Main(string[] args){foreach (string item in SimpleList())Console.WriteLine(item);Console.ReadKey();}}
}

輸出
在這里插入圖片描述

  • 迭代一個類 Enumerator

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace Ch11Ex03
{public class Primes{private long min;private long max;public Primes(): this(2, 100){}public Primes(long minimum, long maximum){if (minimum < 2)min = 2;elsemin = minimum;max = maximum;}public IEnumerator GetEnumerator(){for (long possiblePrime = min; possiblePrime <= max; possiblePrime++){bool isPrime = true;for (long possibleFactor = 2; possibleFactor <=(long)Math.Floor(Math.Sqrt(possiblePrime)); possibleFactor++){long remainderAfterDivision = possiblePrime % possibleFactor;if (remainderAfterDivision == 0){isPrime = false;break;}}if (isPrime){yield return possiblePrime;}}}}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace Ch11Ex03
{class Program{static void Main(string[] args){Primes primesFrom2To1000 = new Primes(2, 1000);//Primes primesFrom2To1000 = new Primes( );foreach (long i in primesFrom2To1000)Console.Write("{0} ", i);Console.ReadKey();}}
}

primesFrom2To1000 為定義的一個類,在foreach里迭代這個類,
yield return possiblePrime;
為迭代要輸出的值,輸出的值的類型為定義的 long possiblePrime

輸出如下
在這里插入圖片描述

3.2、

四、深度復制與淺度復制

4.1、解析及示例

在C#中,深度復制(Deep Copy)淺度復制(Shallow Copy)是處理對象復制時的兩種不同方式,它們的核心區別在于是否遞歸復制對象的所有成員。以下是詳細解釋和示例:

1. 淺度復制(Shallow Copy)

  • 定義:創建一個新對象,但只復制對象的頂層成員。對于引用類型的成員,只復制引用(內存地址),而不復制實際對象。
  • 特點
    • 新對象和原對象是不同的實例(內存地址不同)。
    • 引用類型的成員指向同一個對象。
    • 修改引用類型成員會影響所有關聯的對象。
  • 實現方式
    • 使用 MemberwiseClone() 方法(受保護,需在類內部實現)。
    • 手動復制每個字段。

示例代碼

public class Address
{public string City { get; set; }
}public class Person
{public string Name { get; set; } // 值類型public Address Address { get; set; } // 引用類型// 實現淺復制方法public Person ShallowCopy(){return (Person)this.MemberwiseClone();}
}// 使用示例
Person original = new Person
{Name = "張三",Address = new Address { City = "北京" }
};Person shallowCopy = original.ShallowCopy();// 修改淺復制對象的引用類型成員
shallowCopy.Address.City = "上海";Console.WriteLine(original.Address.City); // 輸出: 上海(被修改了)

2. 深度復制(Deep Copy)

  • 定義:創建一個新對象,并遞歸復制對象的所有成員。對于引用類型的成員,會創建新的對象實例,而非僅復制引用。
  • 特點
    • 新對象和原對象完全獨立,沒有共享的引用類型成員。
    • 修改任何一個對象都不會影響其他對象。
  • 實現方式
    • 手動遞歸復制每個引用類型成員。
    • 使用序列化和反序列化(需類標記為 [Serializable])。

示例代碼(手動實現)

public class Address
{public string City { get; set; }// 提供深度復制方法public Address DeepCopy(){return new Address { City = this.City };}
}public class Person
{public string Name { get; set; }public Address Address { get; set; }// 實現深度復制方法public Person DeepCopy(){return new Person{Name = this.Name,Address = this.Address.DeepCopy() // 遞歸復制引用類型};}
}// 使用示例
Person original = new Person
{Name = "張三",Address = new Address { City = "北京" }
};Person deepCopy = original.DeepCopy();// 修改深度復制對象的引用類型成員
deepCopy.Address.City = "上海";Console.WriteLine(original.Address.City); // 輸出: 北京(未被修改)

示例代碼(使用序列化)

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;[Serializable] // 必須標記為可序列化
public class Address
{public string City { get; set; }
}[Serializable]
public class Person
{public string Name { get; set; }public Address Address { get; set; }// 使用序列化實現深度復制public Person DeepCopy(){using (MemoryStream stream = new MemoryStream()){BinaryFormatter formatter = new BinaryFormatter();formatter.Serialize(stream, this);stream.Position = 0;return (Person)formatter.Deserialize(stream);}}
}
  1. 對比表格
    | 特性 | 淺度復制 | 深度復制 |
    |------------------------|------------------------------|------------------------------|
    | 新對象實例 | 創建頂層對象 | 創建所有層級的對象 |
    | 引用類型成員 | 共享同一個實例 | 創建新實例 |
    | 值類型成員 | 復制值 | 復制值 |
    | 實現復雜度 | 低(使用 MemberwiseClone) | 高(遞歸或序列化) |
    | 修改影響 | 影響所有共享引用的對象 | 僅影響當前對象 |
    | 性能 | 高(僅復制引用) | 低(需創建多個對象) |

  2. 常見問題

  • 循環引用:深度復制時需小心處理循環引用,可能導致棧溢出。
  • 不可序列化類型:使用序列化方法時,所有成員必須可序列化。
  • 性能開銷:深度復制涉及創建多個對象,對性能有影響。
  1. 選擇建議
  • 使用淺度復制:當對象的引用類型成員是不可變的,或不需要獨立修改時。
  • 使用深度復制:當需要完全獨立的對象,避免修改相互影響時。

總結

  • 淺度復制:復制頂層對象,共享引用類型成員。
  • 深度復制:遞歸復制所有成員,創建完全獨立的對象。

理解這兩種復制方式的區別,有助于避免在代碼中出現意外的副作用,并根據需求選擇合適的復制策略。

五、引用和值類型

在C#中,變量類型分為值類型引用類型,它們在內存存儲、傳遞方式和生命周期等方面有本質區別。以下是常見的值類型和引用類型及其特點:

一、值類型(Value Types)

值類型變量直接存儲數據值,通常分配在棧(Stack)上(局部變量)或結構體中。值類型的復制會創建獨立的副本。

  1. 內置值類型
分類類型示例
整數byte, sbyte, short, ushort, int, uint, long, ulongint age = 30;
浮點數float, double, decimaldouble price = 9.99;
布爾boolbool isActive = true;
字符charchar letter = 'A';
枚舉enum(自定義)enum Color { Red, Green, Blue };
元組(int, string)(C# 7.0+)var person = (1, "Alice");
  1. 結構體(Struct)
    結構體是用戶自定義的值類型,常用于輕量級數據存儲:
public struct Point
{public int X;public int Y;
}Point p1 = new Point { X = 10, Y = 20 };
Point p2 = p1; // 復制值,p2與p1獨立
  1. 可空值類型(Nullable)
    允許值類型變量存儲 null
int? nullableInt = null; // 可空整數
bool? nullableBool = false;

二、引用類型(Reference Types)

引用類型變量存儲對象的內存地址(引用),對象本身分配在堆(Heap)上。引用類型的復制僅傳遞引用,多個變量可能指向同一對象。

  1. 內置引用類型
分類類型示例
字符串stringstring name = "John";
數組T[](任意類型的數組)int[] numbers = new int[5];
集合List<T>, Dictionary<TKey, TValue>, HashSet<T>List<string> names = new List<string>();
  1. 類(Class)
    類是最常見的引用類型,包括自定義類和框架類:
public class Person
{public string Name { get; set; }
}Person p1 = new Person { Name = "Alice" };
Person p2 = p1; // 復制引用,p2和p1指向同一對象
  1. 接口(Interface)
    接口本身不能實例化,但實現接口的類是引用類型:
public interface IAnimal
{void Speak();
}public class Dog : IAnimal
{public void Speak() => Console.WriteLine("Woof!");
}IAnimal animal = new Dog(); // 引用類型
  1. 委托(Delegate)
    委托是方法的類型安全引用,屬于引用類型:
public delegate void MyDelegate(string message);MyDelegate del = Console.WriteLine; // 委托實例
  1. 對象(Object)
    所有類型的基類,可引用任何類型的對象:
object obj = "Hello"; // 引用字符串對象
obj = 123; // 引用整數對象(裝箱)
  1. 動態類型(Dynamic)
    在運行時確定類型,屬于引用類型:
dynamic dynamicVar = "Hello";
dynamicVar = 123; // 運行時有效

三、關鍵區別總結

特性值類型引用類型
存儲位置棧或結構體
復制方式創建獨立副本復制引用(共享對象)
默認值0, false, null(可空類型)null
基類System.ValueTypeSystem.Object
常見類型基本數據類型、結構體、枚舉類、接口、數組、字符串、委托

四、特殊注意事項

  1. 字符串的不可變性string 是引用類型,但由于不可變性,賦值時看似創建了副本:

    string a = "Hello";
    string b = a; // 復制引用,但字符串不可變
    b = "World";  // b指向新字符串,a不受影響
    
  2. 裝箱與拆箱:值類型與 object 之間的轉換會產生性能開銷:

    int num = 100;
    object boxed = num; // 裝箱(值類型→引用類型)
    int unboxed = (int)boxed; // 拆箱(引用類型→值類型)
    
  3. 結構體與類的選擇

    • 結構體:輕量級、頻繁創建/銷毀、數據獨立。
    • :復雜行為、需要繼承、共享狀態。

理解值類型和引用類型的區別是編寫高效、安全C#代碼的基礎。根據場景選擇合適的類型,可以避免內存泄漏、提高性能并減少錯誤。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/89910.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/89910.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/89910.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

04 51單片機之數碼管顯示

文章目錄1、前言2、數碼管3、單個數碼管引腳定義3-1、單個共陰極3-2、單個共陽極3-3、單個數碼管引腳定義4、四位一體數碼管引腳定義4-1、四位一體共陰極數碼管4-2、四位一體共陽極數碼管4-3、四位一體數碼管引腳定義5、數碼管原理圖6、C51數組&#xff08;補充知識點&#xff…

【LLM】OpenRouter調用Anthropic Claude上下文緩存處理

背景 在使用OpenRouter調用Anthropic Claude大模型時&#xff0c;部分模型支持上下文緩存功能。當緩存命中時&#xff0c;調用成本會顯著降低。雖然像DeepSeek這類模型自帶上下文緩存機制&#xff0c;但本文主要針對構建Agent場景下&#xff0c;需要多次調用Anthropic Claude時…

【C++】第十七節—二叉搜索樹(概念+性能分析+增刪查+實現+使用場景)

好久不見&#xff0c;我是云邊有個稻草人 《C》本文所屬專欄—持續更新中—歡迎訂閱 目錄 一、二叉搜索樹的概念 二、二叉搜索樹的性能分析 三、二叉搜索樹的插入 SearchBinaryTree.h test.cpp 四、?叉搜索樹的查找 【只有一個3】 【有多個3】 五、?叉搜索樹的刪除…

Redis都有哪些數據結構,使用場景與原理解析

? String&#xff1a;字符串&#xff08;最常用、最簡單的類型&#xff09;&#x1f4cc; 應用場景&#xff1a;計數器&#xff08;如&#xff1a;頁面瀏覽量、點贊數、轉發數等&#xff09;緩存單個值&#xff08;如&#xff1a;token、驗證碼、用戶昵稱&#xff09;分布式鎖…

將EXCEL或者CSV轉換為鍵值對形式的Markdown文件

# 創建命令行參數解析器parser argparse.ArgumentParser(description將 CSV 或 Excel 文件轉換為帶標頭的 Markdown 格式)# 必需參數parser.add_argument(input_file, help輸入文件路徑 (CSV 或 Excel))parser.add_argument(output_file, help輸出 Markdown 文件路徑)# 可選參…

MySQL 配置性能優化實操指南:分版本5.7和8.0適配方案

在 MySQL 性能優化中&#xff0c;不同版本的特性差異會直接影響優化效果。本文基于 MySQL 5.7 和 8.0 兩個主流版本&#xff0c;通過版本適配的配置代碼、場景舉例和通俗解釋&#xff0c;讓優化方案更精準落地。一、硬件與系統配置優化&#xff08;基礎層優化&#xff09;1. 服…

【STM32實踐篇】:串口通信

文章目錄1. 串行通信與并行通信2. 異步通信與同步通信3. 單工&#xff0c;半雙工和全雙工通信4. 通信速率和接口標準5. USART 結構框圖6. 串口電路6.1 串口之間的連接6.2 串口與 RS232 的轉換和連接6.3 串口與 RS485 的轉換和連接6.4 串口與 USB 的轉換和連接7. USART 字符說明…

Trae IDE評測體驗:通過 MCP Server - Figma AI Bridge 一鍵將 Figma 轉為前端代碼

Trae IDE評測體驗&#xff1a;通過 MCP Server - Figma AI Bridge 一鍵將 Figma 轉為前端代碼 在現代前端開發中&#xff0c;從設計稿到可用頁面的交付往往需要大量重復勞動&#xff1a;切圖、手寫樣式、布局調整……而借助 MCP Server - Figma AI Bridge&#xff0c;我們可以…

文獻閱讀 250715-Atmospheric rivers cause warm winters and extreme heat events

Atmospheric rivers cause warm winters and extreme heat events 來自 <Atmospheric rivers cause warm winters and extreme heat events | Nature> ## Abstract: Definition: Atmospheric rivers (ARs) are narrow regions of intense water vapour transport in the …

線上協同辦公時代:以開源AI大模型等工具培養網感,擁抱職業變革

摘要&#xff1a;在提倡線上協同辦公的時代背景下&#xff0c;職場人需迅速提升工作能力以適應職業變革。培養網感成為時代所需&#xff0c;它為快速連接時代奠定基礎。本文深入探討了開源AI大模型、AI智能名片、S2B2C商城小程序源碼等工具在培養網感過程中的重要作用&#xff…

Netty網絡聊天室及擴展序列化算法

一、前言Netty是一個基于Java的高性能、事件驅動的網絡應用框架&#xff0c;廣泛應用于各種網絡通信場景。本文將介紹如何使用Netty構建一個簡單的網絡聊天室&#xff0c;并擴展序列化算法來提高數據傳輸效率和靈活性。二、Netty網絡聊天室的實現1. 項目結構我們將使用Maven構建…

基于單片機金沙河糧倉環境監測系統設計與實現

摘 要 本文圍繞基于單片機的金沙河糧倉環境監測系統展開設計與實現研究。系統以單片機為核心&#xff0c;集成 DHT11、MQ - 135 等傳感器&#xff0c;可實時精準監測糧倉溫濕度、氣體成分等關鍵環境參數。借助 LoRa、ESP8266 實現數據的可靠傳輸與遠程通信 &#xff0c;OLED 屏…

如何解決Android Studio安裝時無法下載SDK的問題(Windows、Linux、Mac解決方案大全)

如何解決Android Studio安裝時無法下載SDK的問題&#xff08;Windows、Linux、Mac解決方案大全&#xff09; 前言 對于全棧開發者而言&#xff0c;安裝 Android Studio 是邁向 Android 開發的第一步&#xff0c;但在 Windows、Linux、macOS 等不同平臺上&#xff0c;經常會遇…

SQL Server從入門到項目實踐(超值版)讀書筆記 21

9.5 數據的內連接查詢連接是關系數據庫模型的主要特點&#xff0c;連接查詢是關系數據庫中最主要的查詢&#xff0c;主要包括內連接、外連接等。內連接查詢操作列出與連接條件匹配的數據行&#xff0c;它使用比較運算符比較被鏈接列的列值。具體語法格式如下&#xff1a;SELECT…

瑞芯微7月17日舉辦開發者大會,多款AIoT新品發布,觸覺智能RK方案商報導

瑞芯微第九屆開發者大會RKDC 2025將有多款新品發布。 據瑞芯微電子Rockchip此前宣布&#xff1a;該企業的本年度開發者大會RKDC 2025將于7月17~18日在福建福州海峽國際會展中心舉行。本次瑞芯微開發者大會以“AIoT模型創新重做產品”為主題&#xff0c;關注傳統IoT功能設備向場…

Eureka+Ribbon實現服務注冊與發現

目錄 一、相關文章 二、兼容說明 三、服務注冊 四、服務發現 一、相關文章 基礎工程&#xff1a;gradle7.6.1springboot3.2.4創建微服務工程-CSDN博客 Eureka服務端啟動&#xff1a;https://blog.csdn.net/cherishSpring/article/details/149473554 Ribbon負載均衡&#…

數據庫、HTML

一、數據庫 數據庫文件與普通文件區別: 普通文件對數據管理(增刪改查)效率低2.數據庫對數據管理效率高&#xff0c;使用方便 常用數據庫: 1.關系型數據庫: 將復雜的數據結構簡化為二維表格形式 大型:0racle、DB2 中型:MySq1、sQLServer 小型:Sqlite 2.非關系型數據庫以鍵值對…

RCE隨筆(1)

哪些是可以執行代碼執行&#xff1a;php代碼。eval如&#xff1a;eval:<?php eval($_post[key]);eval&#xff1a;php中不被叫做函數叫動態執行命令assert&#xff1a;執行函數call_user_func_array<?php call_user_func_array(assert,array($_REQUEST[shu]));傳入xxs-…

FPGA——ZYNQ7020學習日記(PS端)4(開始PS控制VGA顯示)

1.DMA 我們的整體VGA顯示分為幾步&#xff1a;比如先導入VIDEO TIMING CONTROL來做對輸入數據的時序“對齊”&#xff0c;這里開源騷客寫的很詳細&#xff0c;先用了一個虛擬IO&#xff08;VIO)來作為輸入&#xff0c;導入了一個簡單的RTL模塊&#xff08;當VTL的使能信號有效…

AGX Xavier 搭建360環視教程【補充一:魚眼去畸變(Fisheye Undistortion)】

對每路幀做魚眼去畸變除了用cv::cuda::remap是否有更好的辦法呢&#xff1f;確實 cv::cuda::remap 不是唯一可選項&#xff0c;甚至未必是最高效或最適合實際業務量級的方案。&#x1f3af; 1?? 去畸變的原理魚眼相機&#xff08;或者大廣角相機&#xff09;會把直線拉彎&…