当前位置: 首页 > news >正文

C#面试题及详细答案120道(21-30)-- 集合与泛型

前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。

前后端面试题-专栏总目录

在这里插入图片描述

文章目录

  • 一、本文面试题目录
      • 21. 简述C#中常用的集合类型及其特点(List、Dictionary、HashSet等)
      • 22. Array和ArrayList的区别
      • 23. List<T>和ArrayList的区别
      • 24. Dictionary<TKey, TValue>的实现原理是什么?如何解决哈希冲突?
      • 25. 什么是泛型?泛型的优点是什么?
      • 26. 泛型约束有哪些类型?如何使用?
      • 27. 什么是协变和逆变?在泛型中如何实现?
      • 28. IEnumerable和IEnumerator的区别
      • 29. ICollection和IList接口的区别
      • 30. 什么是 HashSet<T>?与 List<T> 相比有什么优势?
  • 二、120道C#面试题目录列表

一、本文面试题目录

21. 简述C#中常用的集合类型及其特点(List、Dictionary、HashSet等)

C#提供了多种集合类型,适用于不同场景,以下是常用集合及其特点:

  1. List

    • 特点:动态大小的泛型列表,基于数组实现
    • 优势:随机访问效率高(O(1)),支持索引操作
    • 劣势:插入/删除中间元素效率低(O(n))
    • 适用场景:需要频繁访问元素、顺序存储数据
    var list = new List<int> { 1, 2, 3 };
    list.Add(4);
    int value = list[2]; // 随机访问
    
  2. Dictionary<TKey, TValue>

    • 特点:键值对集合,基于哈希表实现
    • 优势:按键查找效率高(O(1)),支持快速插入
    • 劣势:无序存储,键不能重复
    • 适用场景:需要通过唯一键快速查找数据
    var dict = new Dictionary<string, int>();
    dict["one"] = 1;
    int num = dict["one"]; // 快速查找
    
  3. HashSet

    • 特点:不重复元素的集合,基于哈希表实现
    • 优势:检查元素是否存在效率高(O(1)),自动去重
    • 劣势:无序,不能通过索引访问
    • 适用场景:需要去重、集合运算(交集、并集)
    var set = new HashSet<int> { 1, 2, 3 };
    bool exists = set.Contains(2); // 快速检查存在性
    
  4. Queue

    • 特点:先进先出(FIFO)的队列
    • 优势:入队/出队操作高效(O(1))
    • 适用场景:消息队列、任务调度
    var queue = new Queue<string>();
    queue.Enqueue("first");
    string item = queue.Dequeue(); // 获取并移除第一个元素
    
  5. Stack

    • 特点:后进先出(LIFO)的栈
    • 优势:入栈/出栈操作高效(O(1))
    • 适用场景:表达式计算、回溯算法
    var stack = new Stack<int>();
    stack.Push(1);
    int top = stack.Pop(); // 获取并移除顶部元素
    
  6. LinkedList

    • 特点:双向链表实现
    • 优势:插入/删除中间元素效率高(O(1),已知节点时)
    • 劣势:随机访问效率低(O(n))
    • 适用场景:频繁插入删除且不需要随机访问
  7. SortedDictionary<TKey, TValue>

    • 特点:按键排序的键值对集合,基于红黑树实现
    • 优势:自动排序,范围查询高效
    • 劣势:插入/查找效率略低于Dictionary(O(log n))

22. Array和ArrayList的区别

Array(数组)和ArrayList都是用于存储多个元素的集合,但存在以下关键区别:

特性ArrayArrayList
类型安全强类型,只能存储声明类型的元素弱类型,存储object类型,可混合不同类型
大小固定大小,创建后不能改变动态大小,自动扩容
泛型支持非泛型(C# 2.0后有泛型数组)非泛型,始终存储object
性能更高,无需装箱拆箱(值类型)较低,值类型需要装箱拆箱
方法支持基本方法(Length等)丰富的方法(Add、Remove、Sort等)
索引器支持支持

示例代码

// Array示例
int[] numbers = new int[3]; // 固定大小
numbers[0] = 1;
numbers[1] = 2;
// numbers[3] = 3; // 错误:超出数组范围// ArrayList示例
ArrayList arrayList = new ArrayList(); // 动态大小
arrayList.Add(1);       // 装箱
arrayList.Add("hello"); // 可以添加不同类型
arrayList.Add(3.14);
int first = (int)arrayList[0]; // 拆箱

使用建议

  • 需要固定大小、强类型集合时用Array
  • 需要动态大小且元素类型多样时用ArrayList(但建议优先用List)
  • 避免在高性能场景使用ArrayList(因装箱拆箱开销)

23. List和ArrayList的区别

List和ArrayList都是动态大小的集合,但List是泛型实现,两者区别如下:

特性ListArrayList
类型安全强类型,只允许T类型元素弱类型,允许任何类型(存储为object)
装箱拆箱不需要(值类型也无需转换)需要(值类型存储和读取时)
性能更高(避免类型转换开销)较低(装箱拆箱和类型检查)
编译时检查有,错误在编译时发现无,错误可能在运行时才发现
命名空间System.Collections.GenericSystem.Collections
兼容性.NET 2.0+(泛型引入后).NET 1.0+

示例代码对比

// List<T>示例(强类型)
List<int> intList = new List<int>();
intList.Add(10);
intList.Add(20);
// intList.Add("30"); // 编译错误:类型不匹配
int sum = intList[0] + intList[1]; // 无需类型转换// ArrayList示例(弱类型)
ArrayList arrayList = new ArrayList();
arrayList.Add(10);      // 装箱
arrayList.Add("20");    // 允许不同类型
// 运行时错误(string不能转换为int)
// int sum = (int)arrayList[0] + (int)arrayList[1];

性能测试示例

// 性能对比:添加100万整数
Stopwatch sw = new Stopwatch();// List<int>
sw.Start();
var list = new List<int>();
for (int i = 0; i < 1000000; i++)list.Add(i);
sw.Stop();
Console.WriteLine($"List耗时: {sw.ElapsedMilliseconds}ms");// ArrayList
sw.Restart();
var arrayList = new ArrayList();
for (int i = 0; i < 1000000; i++)arrayList.Add(i); // 产生装箱
sw.Stop();
Console.WriteLine($"ArrayList耗时: {sw.ElapsedMilliseconds}ms");

输出通常为

List耗时: 15ms
ArrayList耗时: 45ms

结论:除非需要兼容旧代码或存储多种类型元素,否则应优先使用List。

24. Dictionary<TKey, TValue>的实现原理是什么?如何解决哈希冲突?

Dictionary<TKey, TValue> 是基于哈希表实现的键值对集合,其核心原理和哈希冲突解决机制如下:

实现原理

  1. 内部结构:包含一个存储键值对的数组(Entry[]),每个元素是一个结构体,包含Key、Value、哈希码和下一个元素索引
  2. 哈希计算:对键进行哈希计算,得到哈希码
  3. 索引计算:通过哈希码和数组长度计算存储位置(索引)
  4. 存储数据:将键值对存储到计算出的索引位置

基本操作流程

添加元素:
Key → 计算哈希码 → 计算索引 → 存储到数组对应位置查找元素:
Key → 计算哈希码 → 计算索引 → 从对应位置查找匹配的Key

哈希冲突:不同的Key可能计算出相同的索引,这种情况称为哈希冲突。Dictionary采用链地址法解决冲突:

  1. 每个数组位置(桶)可以形成一个链表
  2. 发生冲突时,新元素会被添加到对应桶的链表末尾
  3. 查找时,先定位到桶,再遍历链表查找匹配的Key

示意图

数组索引: 0    1    2    3↓    ↓    ↓    ↓
元素:  [Entry] → [Entry]  [Entry]→ [Entry]

代码示例

var dict = new Dictionary<string, int>();
dict.Add("apple", 1);
dict.Add("banana", 2);
dict.Add("cherry", 3);// 查找元素(内部经历哈希计算和可能的链表遍历)
if (dict.TryGetValue("banana", out int value))
{Console.WriteLine($"找到值: {value}");
}

冲突处理的影响

  • 少量冲突对性能影响不大
  • 大量冲突会使查找退化为O(n)复杂度(类似链表)
  • Dictionary会在负载因子(元素数/桶数)超过阈值(默认0.72)时自动扩容,减少冲突

关键优化

  • 扩容时创建更大的数组(通常是原大小的2倍)
  • 重新计算所有元素的哈希和索引,分散存储
  • 优质的哈希函数可减少冲突,提高性能

25. 什么是泛型?泛型的优点是什么?

泛型是允许在定义类、接口、方法时使用未指定的类型(类型参数),在使用时再指定具体类型的技术。

基本语法

// 泛型类
public class GenericList<T>
{// 泛型方法public void Add(T item) { }// 泛型属性public T this[int index] { get; set; }
}

使用示例

// 使用时指定具体类型
var intList = new GenericList<int>();
intList.Add(10);
int value = intList[0];var stringList = new GenericList<string>();
stringList.Add("hello");

泛型的主要优点

  1. 类型安全

    • 编译时检查类型,避免运行时类型转换错误
    • 示例:List<int>只能添加int类型,编译时阻止添加string
  2. 消除装箱拆箱

    • 值类型无需转换为object,提高性能
    • 对比:ArrayList添加int会装箱,List<int>不会
  3. 代码复用

    • 一套代码支持多种数据类型,减少重复代码
    • 示例:List<T>可用于int、string等任何类型
  4. 更好的性能

    • 避免类型转换的性能开销
    • 对于值类型集合,性能提升尤为明显
  5. 清晰的代码意图

    • 明确指定集合或方法支持的类型
    • 提高代码可读性和可维护性

泛型方法示例

// 泛型方法:交换两个值
public static void Swap<T>(ref T a, ref T b)
{T temp = a;a = b;b = temp;
}// 使用
int x = 1, y = 2;
Swap(ref x, ref y); // 交换intstring s1 = "hello", s2 = "world";
Swap(ref s1, ref s2); // 交换string

总结:泛型是C#中非常重要的特性,通过类型参数化实现了类型安全、代码复用和性能优化,广泛应用于集合类、算法实现等场景。

26. 泛型约束有哪些类型?如何使用?

泛型约束用于限制类型参数可以接受的类型,确保类型参数具有特定的功能,语法为where 类型参数 : 约束

C#支持以下6种泛型约束:

  1. 值类型约束(struct)

    • 限制类型参数必须是值类型(int、struct等)
    public class NumericProcessor<T> where T : struct
    {// T必须是值类型
    }
    
  2. 引用类型约束(class)

    • 限制类型参数必须是引用类型(class、interface等)
    public class ReferenceHandler<T> where T : class
    {// T必须是引用类型
    }
    
  3. 无参数构造函数约束(new())

    • 限制类型参数必须有公共无参数构造函数
    • 必须放在约束列表的最后
    public class ObjectCreator<T> where T : new()
    {public T Create() => new T(); // 可以安全地创建实例
    }
    
  4. 基类约束

    • 限制类型参数必须是指定基类或其派生类
    public class AnimalHandler<T> where T : Animal
    {public void Feed(T animal){animal.Eat(); // 可以调用基类方法}
    }
    
  5. 接口约束

    • 限制类型参数必须实现指定接口
    public class SortableCollection<T> where T : IComparable<T>
    {public void Sort(T[] items){Array.Sort(items); // 依赖IComparable接口}
    }
    
  6. 另一个类型参数约束

    • 限制一个类型参数必须是另一个类型参数的派生类
    public class DerivedConstraint<T, U> where T : U
    {// T必须是U的派生类型
    }
    

多重约束示例

// 多重约束:T必须是引用类型、实现IDisposable、有默认构造函数
public class ResourceManager<T> where T : class, IDisposable, new()
{public T GetResource(){return new T(); // 因new()约束}public void ReleaseResource(T resource){resource.Dispose(); // 因IDisposable约束}
}

约束的作用

  • 使泛型代码可以安全地调用类型参数的方法和属性
  • 缩小类型参数范围,提高类型安全性
  • 编译器可以提供更好的类型检查和IntelliSense支持

注意:如果没有约束,泛型代码只能使用object类的成员。

27. 什么是协变和逆变?在泛型中如何实现?

协变(Covariance)逆变(Contravariance) 是描述泛型类型参数在继承关系中的转换行为的概念,允许派生类型的泛型与基类型的泛型之间进行转换。

基本概念

  • 协变:允许从Generic<Derived>转换为Generic<Base>(与继承方向相同)
  • 逆变:允许从Generic<Base>转换为Generic<Derived>(与继承方向相反)

实现方式
在泛型接口或委托中,使用out关键字声明协变类型参数,使用in关键字声明逆变类型参数。

协变示例(out关键字)

// 协变接口(out关键字)
public interface ICovariant<out T>
{T GetItem(); // T只能作为返回值
}public class CovariantImplementation<T> : ICovariant<T>
{public T GetItem() => default(T);
}// 继承关系
public class Animal { }
public class Dog : Animal { }// 使用协变
ICovariant<Dog> dogCovariant = new CovariantImplementation<Dog>();
ICovariant<Animal> animalCovariant = dogCovariant; // 允许转换(协变)

逆变示例(in关键字)

// 逆变接口(in关键字)
public interface IContravariant<in T>
{void SetItem(T item); // T只能作为参数
}public class ContravariantImplementation<T> : IContravariant<T>
{public void SetItem(T item) { }
}// 使用逆变
IContravariant<Animal> animalContravariant = new ContravariantImplementation<Animal>();
IContravariant<Dog> dogContravariant = animalContravariant; // 允许转换(逆变)

内置协变和逆变接口

  • 协变:IEnumerable<out T>IQueryable<out T>
  • 逆变:IComparer<in T>IEqualityComparer<in T>

使用示例

// 协变:IEnumerable<out T>
IEnumerable<Dog> dogs = new List<Dog>();
IEnumerable<Animal> animals = dogs; // 协变转换// 逆变:Action<in T>委托
Action<Animal> feedAnimal = (a) => { };
Action<Dog> feedDog = feedAnimal; // 逆变转换

限制条件

  • 协变(out):类型参数只能作为返回值或只读属性
  • 逆变(in):类型参数只能作为方法参数
  • 仅适用于接口和委托,类和结构不支持
  • 值类型不参与协变和逆变(如List<int>不能转换为IEnumerable<object>

作用:提高泛型类型的灵活性,使泛型代码更好地支持多态。

28. IEnumerable和IEnumerator的区别

IEnumerableIEnumerator是C#中用于支持迭代(遍历)集合的核心接口,两者分工不同但协同工作。

IEnumerable接口

  • 表示"可枚举的"集合,提供获取枚举器的方法
  • 定义了一个方法:GetEnumerator(),返回IEnumerator
  • 实现此接口的类可以使用foreach循环遍历

IEnumerator接口

  • 表示"枚举器",负责实际遍历集合的元素
  • 定义了三个成员:
    • Current:获取当前元素
    • MoveNext():移动到下一个元素,返回是否成功
    • Reset():重置枚举器到初始位置

工作流程

  1. foreach循环调用集合的IEnumerable.GetEnumerator()获取枚举器
  2. 调用IEnumerator.MoveNext()移动到第一个元素
  3. 通过IEnumerator.Current访问当前元素
  4. 重复步骤2-3直到MoveNext()返回false
  5. 自动释放枚举器(如果实现了IDisposable

示例代码

// 实现IEnumerable的集合
public class MyCollection : IEnumerable
{private int[] items = { 1, 2, 3, 4 };// 实现IEnumerable:返回枚举器public IEnumerator GetEnumerator(){return new MyEnumerator(items);}
}// 实现IEnumerator的枚举器
public class MyEnumerator : IEnumerator
{private int[] items;private int position = -1;public MyEnumerator(int[] items){this.items = items;}// 获取当前元素public object Current{get{if (position < 0 || position >= items.Length)throw new InvalidOperationException();return items[position];}}// 移动到下一个元素public bool MoveNext(){position++;return position < items.Length;}// 重置枚举器public void Reset(){position = -1;}
}// 使用示例
var collection = new MyCollection();
foreach (int item in collection) // 使用IEnumerable
{Console.WriteLine(item);
}

泛型版本

  • IEnumerable<T>:泛型可枚举接口,返回IEnumerator<T>
  • IEnumerator<T>:泛型枚举器接口,Current属性返回T类型
  • 泛型版本避免了装箱拆箱,更类型安全

区别总结

  • IEnumerable:定义集合"可被枚举"的能力,提供获取枚举器的入口
  • IEnumerator:实现实际的枚举逻辑,控制遍历过程
  • 关系:IEnumerable依赖IEnumerator完成遍历

29. ICollection和IList接口的区别

ICollectionIList都是System.Collections命名空间中的核心接口,用于定义集合的功能,两者的继承关系和功能不同:

继承关系

  • IList继承自ICollectionIEnumerable
  • ICollection继承自IEnumerable

功能区别

接口核心功能主要成员适用场景
ICollection定义基本的集合操作(计数、复制、同步)Count、CopyTo()、IsSynchronized、SyncRoot只需要基本集合功能的场景
IList扩展ICollection,增加索引访问和列表特有操作索引器、Add()、Remove()、Insert()、Contains()、IndexOf()需要通过索引访问、支持插入删除的有序集合

示例代码

// ICollection示例
public void ProcessCollection(ICollection collection)
{Console.WriteLine($"集合有{collection.Count}个元素");// 复制到数组object[] array = new object[collection.Count];collection.CopyTo(array, 0);
}// IList示例
public void ProcessList(IList list)
{// IList继承了ICollection的功能Console.WriteLine($"列表有{list.Count}个元素");// IList特有的功能list.Add("new item"); // 添加元素list.Insert(0, "first"); // 插入元素int index = list.IndexOf("first"); // 查找索引object item = list[0]; // 索引访问list.RemoveAt(0); // 删除元素
}

泛型版本

  • ICollection<T>:泛型版本,增加了Add(T)Remove(T)等强类型方法
  • IList<T>:泛型版本,提供强类型的索引器和列表操作

泛型IList示例

public void ProcessGenericList(IList<string> list)
{list.Add("hello"); // 强类型添加,编译时检查string first = list[0]; // 无需类型转换bool contains = list.Contains("world");
}

使用建议

  • 当需要传递一个支持计数和复制的集合时,使用ICollection
  • 当需要索引访问或列表操作(插入、删除)时,使用IList
  • 优先使用泛型版本(ICollection<T>IList<T>)以获得类型安全和更好的性能

30. 什么是 HashSet?与 List 相比有什么优势?

HashSet<T>是基于哈希表实现的泛型集合,用于存储不重复的元素,属于System.Collections.Generic命名空间。

基本特性

  • 元素唯一(自动去重)
  • 无序存储(不保证元素顺序)
  • 基于哈希表,查找效率高
  • 实现了ICollection<T>接口

基本用法

var set = new HashSet<string>();// 添加元素(自动去重)
set.Add("apple");
set.Add("banana");
bool added = set.Add("apple"); // 返回false(已存在)// 检查元素是否存在
bool contains = set.Contains("banana");// 移除元素
set.Remove("banana");// 集合运算
var set1 = new HashSet<int> { 1, 2, 3 };
var set2 = new HashSet<int> { 3, 4, 5 };// 交集
set1.IntersectWith(set2); // set1现在包含{3}// 并集
set1.UnionWith(set2); // 包含{1,2,3,4,5}// 差集
set1.ExceptWith(set2); // 包含{1,2}

与List的优势对比

  1. 元素唯一性

    • HashSet<T>自动确保元素不重复,无需手动检查
    • List<T>需要手动调用Contains()检查后再添加
  2. 查找性能

    • HashSet<T>.Contains():O(1)时间复杂度
    • List<T>.Contains():O(n)时间复杂度
    • 大数据量时,HashSet优势明显
  3. 集合运算支持

    • HashSet<T>内置交集、并集、差集等集合运算方法
    • List<T>需要手动实现这些功能

性能对比示例

var list = new List<int>();
var hashSet = new HashSet<int>();// 填充数据
for (int i = 0; i < 10000; i++)
{list.Add(i);hashSet.Add(i);
}// 测试查找性能
Stopwatch sw = new Stopwatch();// List查找
sw.Start();
bool listContains = list.Contains(9999);
sw.Stop();
Console.WriteLine($"List查找耗时: {sw.ElapsedTicks}");// HashSet查找
sw.Restart();
bool setContains = hashSet.Contains(9999);
sw.Stop();
Console.WriteLine($"HashSet查找耗时: {sw.ElapsedTicks}");

典型输出

List查找耗时: 1250
HashSet查找耗时: 10

适用场景

  • 需要存储唯一元素的场景
  • 频繁检查元素是否存在的操作
  • 需要进行集合运算(交集、并集等)
  • 不关心元素顺序的情况

局限性

  • 不保证元素顺序,不能通过索引访问
  • 元素必须正确实现GetHashCode()Equals()方法

HashSet<T>List<T>都是常用的泛型集合,但各有侧重:当需要快速查找和去重时选择HashSet<T>,当需要维护顺序和索引访问时选择List<T>

二、120道C#面试题目录列表

文章序号C#面试题120道
1C#面试题及详细答案120道(01-10)
2C#面试题及详细答案120道(11-20)
3C#面试题及详细答案120道(21-30)
4C#面试题及详细答案120道(31-40)
5C#面试题及详细答案120道(41-50)
6C#面试题及详细答案120道(51-60)
7C#面试题及详细答案120道(61-75)
8C#面试题及详细答案120道(76-85)
9C#面试题及详细答案120道(86-95)
10C#面试题及详细答案120道(96-105)
11C#面试题及详细答案120道(106-115)
12C#面试题及详细答案120道(116-120)

文章转载自:

http://aqGDfeyd.nbhft.cn
http://vSOqjc8l.nbhft.cn
http://C4R9BglO.nbhft.cn
http://lEaDbEB7.nbhft.cn
http://j6OQR69O.nbhft.cn
http://qefNX2I7.nbhft.cn
http://U7unOzyo.nbhft.cn
http://e1DaM8zq.nbhft.cn
http://r0tU3XH1.nbhft.cn
http://oPCay2XW.nbhft.cn
http://PhtyOUIG.nbhft.cn
http://8cTZafAy.nbhft.cn
http://1g688eqT.nbhft.cn
http://4q98gjLt.nbhft.cn
http://x3dTqMJe.nbhft.cn
http://1s52JaTS.nbhft.cn
http://ZEyOiMxs.nbhft.cn
http://O29YYocW.nbhft.cn
http://xhFulb3o.nbhft.cn
http://STzR0xXu.nbhft.cn
http://LPsskJgx.nbhft.cn
http://JTKbQDG9.nbhft.cn
http://P2c8ETEI.nbhft.cn
http://U2N4KfMI.nbhft.cn
http://336bVJrz.nbhft.cn
http://4Ty4Tfat.nbhft.cn
http://A0mbQ8dK.nbhft.cn
http://EmUriHHX.nbhft.cn
http://3PN38Nq6.nbhft.cn
http://7QRHfZ03.nbhft.cn
http://www.dtcms.com/a/387775.html

相关文章:

  • 如何对AI代理的决策进行审计和监督?
  • .NET驾驭Word之力:玩转文本与格式
  • NLP中Subword算法:WordPiece、BPE、BBPE、SentencePiece详解以及代码实现
  • 解决Dify部署痛点:Docker镜像源优化配置指南
  • 达梦数据库模式
  • Pytorch笔记
  • SQL 数值函数速查:ROUND、CEIL、FLOOR、MOD 怎么用?
  • GPT-5-Codex 正式发布:迈向真正的“自主编程”时代
  • 直播美颜灯MCU控制方案开发设计分享
  • 数据结构(C语言篇):(十六)插入排序
  • 点亮第一个LED灯
  • Python环境》开发环境搭建
  • 【猛犸AI科技】无人机UAV边缘计算MEC实验
  • 【Datawhale25年9月组队学习:llm-preview+Task1:大模型介绍与环境配置】
  • 【MySQL】体系结构
  • Gated Attention 论文阅读
  • Git 命令行教程:配置 SSH 密钥高效克隆与管理项目
  • 机器学习和数据科学的开源 Python 库-Streamlit
  • Roo Code 的Enhance Prompt「增强提示」功能详解
  • 检测IP是否正常的方法
  • JMeter线程组
  • Flink基于Paimon的实时湖仓解决方案的演进
  • 29、生成模型入门-从数据重构到智能创造
  • Dokcer的安装(ubuntu-20.04.6):
  • 梳理Axios请求的过程和 Vite 代理配置
  • 元宇宙与电竞产业:沉浸式交互重构电竞全链条生态
  • 【pycharm】index-tts2:之二 :ubuntu24.04重建UV虚拟环境
  • 点评项目(Redis中间件)数据操作相关知识总结
  • 从0死磕全栈第九天:Trae AI IDE一把梭,使用react-query快速打通前后端接口调试
  • 【论文阅读】MIDAS: 多模态交互式数字人合成,通过实时自回归视频生成