c#学习笔记

PInvoke互操作技术

代码编写

  • c++编写
--- Person.cpp

extern "C"
{
    _declspec(dllexport) int Sum(int a, int b);
}


--- Person.h

#include "Person.h"
#include "iostream"
using namespace std;

int Sum(int a, int b)
{
    return a + b;
}
  • c#调用
    class Program
    {
        [DllImport("ConsoleApplication1.dll", CallingConvention = CallingConvention.Cdecl)]
        extern static int Sum(int a, int b);

        static void Main(string[] args)
        {
            var result = Sum(10, 20);

            Console.WriteLine($"10+20={result}");

            Console.ReadLine();
        }
    }

---- output -----

10+20=30
  • c#编写,c++调用
 --- main.cs
    class Program
    {
        delegate void Callback(int a);

        [DllImport("ConsoleApplication1.dll", CallingConvention = CallingConvention.Cdecl)]
        extern static void AsyncProcess(Callback callback);

        static void Main(string[] args)
        {
            AsyncProcess((i) =>
            {
                //这里回调函数哦...

                Console.WriteLine($"这是回调函数哦: {i}");
            });

            Console.ReadLine();
        }
    }

------- output -------  

这是回调函数哦: 10


--- Person.cpp

extern "C"
{
    //函数指针
    typedef void(_stdcall* PCALLBACK) (int result);
    _declspec(dllexport) void AsyncProcess(PCALLBACK ptr);
}

--- Person.h

#include "Person.h"
#include "iostream"
using namespace std;

void AsyncProcess(PCALLBACK ptr)
{
    ptr(10);  //回调C#的委托
}
  • 传入c++里的内存由c#的垃圾回收器负责释放

  • 当 C++ 函数在堆上分配内存时,内存的释放责任由调用者负责,而不是由 C++ 函数本身负责

环境配置

  • 用vs2019创建C++的Console App,修改两个配置: 将程序导出为dll,修改成compile方式为Compile as C++ Code (/TP)

c#访问控制

  • c#中的成员函数、变量必须保持与类前定义权限一致,与c++相比,必须在类前加访问控制

一般情况(4种)

  • public:public关键字表示类成员对外部代码是完全可见和可访问的。即其他类或代码可以直接访问标记为public的成员。这是最开放的访问级别
  • private:private关键字表示类成员只能在当前类内部访问,其他类无法访问标记为private的成员。这实现了数据隐藏和封装,确保类的实现细节对外部代码是不可见的
  • protected:protected关键字表示类成员只能在当前类内部和其子类中访问。这允许继承体系中的子类访问基类的受保护成员,但对于其他类仍然是不可见的
  • internal:internal关键字表示类成员只能在当前程序集内部访问。这个访问级别对于模块化代码和库的内部实现很有用,它允许不同的程序集使用相同的internal成员,但对于其他程序集是不可见的

特殊情况(2种)

  • protected internal:protected internal关键字表示类成员可以在当前程序集内部和其子类中访问。它是protected和internal的结合,对于继承体系中的子类和同一程序集的其他类都是可见的。
  • private protected:private protected关键字表示类成员可以在同一程序集内部和其派生类中访问,但是对于其他程序集的类是不可见的。它是private和protected的结合

c#标准

c++ & c# 数据结构对比

c++ c #
vector List
map SortedDictionary<TKey, TValue>
set HashSet
queue Queue
stack Stack
priority_queue PriorityQueue
deque LinkedList
unordered_map Dictionary<TKey, TValue>

c#语法

  • 更改字符串的值
char[] chs= s.ToCharArray();
chs[3] = '小';
s = new string(chs);
  • enum
public enum NGType
{
    拔针不良 = 10,
    极耳错位 = 1,
    极耳NG = 2,
    读码NG=3,
    外观AI不良=4
}
/// idx访问(按排列 不按val)
for(int i = 0; i < 5; ++i) 
        Console.WriteLine("{0}\t", (NGType)i);
int idx = 1;
// output:
拔针不良	极耳错位	极耳NG	读码NG	外观AI不良	

  • io相关
// Environment.CurrentDirectory;
  string currentDir = Environment.CurrentDirectory;
  Console.WriteLine("Current directory: " + currentDir);

  // 设置当前工作目录
  string newDir = @"C:\Temp";
  Environment.CurrentDirectory = newDir;
  Console.WriteLine("New current directory: " + Environment.CurrentDirectory);

  // 在新的工作目录下读取文件(假设 C:\Temp 目录下有一个 test.txt 文件)
  string filePath = "test.txt";
  string fullPath = System.IO.Path.Combine(Environment.CurrentDirectory, filePath);
  string content = System.IO.File.ReadAllText(fullPath);
  Console.WriteLine("File content: " + content);
// FileInfo 
  // 文件路径
  string filePath = @"C:\Temp\example.txt";

  // 实例化 FileInfo 对象
  FileInfo fileInfo = new FileInfo(filePath);

  // 获取文件信息
  Console.WriteLine("File Name: " + fileInfo.Name);
  Console.WriteLine("File Full Path: " + fileInfo.FullName);
  Console.WriteLine("Directory: " + fileInfo.Directory);
  Console.WriteLine("File Size: " + fileInfo.Length + " bytes");
  Console.WriteLine("Creation Time: " + fileInfo.CreationTime);
  Console.WriteLine("Last Write Time: " + fileInfo.LastWriteTime);

  // 文件复制和移动
  string destinationPath = @"C:\Temp\newExample.txt";
  fileInfo.CopyTo(destinationPath, true); // true 表示如果目标文件存在,则覆盖
  fileInfo.MoveTo(@"C:\Temp\MovedExample.txt");

  // 文件删除
  fileInfo.Delete();
  • 委托 delegate
    • 可以让你将方法作为参数传递给其他方法,或者在特定条件下执行多个方法
// 委托类型声明
delegate int MyDelegate(int x, int y);

// 创建委托实例,并绑定方法
MyDelegate myDelegate = new MyDelegate(Add);
int result = myDelegate(5, 10); // 调用委托实例,执行绑定的方法
Console.WriteLine("Addition Result: " + result);

// 绑定多个方法,创建委托链
myDelegate += Subtract;
myDelegate += Multiply;
myDelegate += Divide;

// 调用委托链,依次执行绑定的方法
result = myDelegate(20, 5);
Console.WriteLine("Result of Delegate Chain: " + result);
  • System.Text.StringBuilder
    • 相当于c++里的string
System.Text.StringBuilder sb = new System.Text.StringBuilder("Rat: the ideal pet");
sb[0] = 'C';
System.Console.WriteLine(sb.ToString());
//Outputs Cat: the ideal pet
  • enum遍历
foreach (DaysOfWeek day in Enum.GetValues(typeof(DaysOfWeek)))
{
    Console.WriteLine($"{day}: {(int)day}");
}
  • get,set自定义逻辑获值赋值
public class Person
{
    private string name;

    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            // 可以在 set 方法中加入逻辑,例如验证输入值是否合法
            if (!string.IsNullOrEmpty(value))
            {
                name = value;
            }
            else
            {
                Console.WriteLine("Name cannot be empty.");
            }
        }
    }
}

  • GC(Garbage Collection)

    • 是.NET Framework(或.NET Core)中的一种自动内存管理机制,它负责自动回收不再使用的内存,并释放给操作系统。以下是.NET Framework 中的常见 GC 过程:

      • 标记阶段(Marking Phase):GC 会从根对象开始,通过遍历对象图(Object Graph)来标记所有可达的对象。根对象包括全局变量、静态变量以及当前线程的栈上的变量。所有可达的对象会被标记为“存活”。

      • 清理阶段(Sweeping Phase):在标记阶段后,GC 会扫描堆中的所有对象,清理未被标记的对象。未被标记的对象被认为是“垃圾”,会被回收。

      • 压缩阶段(Compacting Phase):在清理阶段后,GC 会对堆中的存活对象进行压缩,将它们移动到一侧,从而使得堆空间变得更加连续,减少内存碎片化问题。

      • 释放阶段(Release Phase):在压缩阶段后,GC 会将不再使用的堆内存释放给操作系统,使得这些内存可以被其他进程或应用程序使用。

    • GC 过程是非常复杂的,并且.NET Framework 提供了不同的 GC 实现(如标记-清除、标记-压缩、并发 GC 等),以适应不同的场景和需求

  • 泛型

    • 类似与c++的模板类
// Declare the generic class.
public class GenericList<T>
{
    public void Add(T input) { }
} 
posted @ 2023-07-21 10:20  InsiApple  阅读(12)  评论(0编辑  收藏  举报