首页 > 编程语言 >C#中的数据类型

C#中的数据类型

时间:2025-01-13 18:31:18浏览次数:3  
标签:变量 C# 数据类型 System int 类型

C#是一种强类型语言,无论是变量、常量,还是方法的参数、返回值,都需要指定相应的数据类型。从某种意义上来说,数据类型就像数据结构的模板,它包含了很多信息:

  1. 一种数据类型所需要的内存空间;

  2. 该数据类型的取值范围,即它可以表示的最大值和最小值;

  3. 它所继承的基类信息;

  4. 运行时它在内存中存储的位置;

  5. 该数据类型本身所支持的操作,比如数字型支持四则运算;

  6. 它自身的成员,如方法、字段、事件,等等。

编译器依赖数据类型来实现类型安全,比如可以对数字型变量实施加减操作,但无法对布尔型执行同样的操作。另外,编译器将数据类型作为元数据放入编译生成的程序集中,进一步保证程序中运行时依赖相应的数据类型进行正确的内存分配和回收,进一步保证类型安全性。

.NET框架已经帮我们定义了大量的基本数据类型,对应表4-2,我们可以看到C#的数据类型和.NET框架数据类型的对应关系,事实上,C#的内置类型关键字只不过是CTS中预定义类型的一个别名而已,它们是等价的,如表4-2所示。

在表4-2中,除了object和string类型外,其他类型都称为简单类型。

因为C#内置类型的关键字就是CTS类型的别名,因此在使用时它们可以互换,而使用CTS类型的别名显然要省事得多,如代码清单4-7所示。

代码清单4-7 C#类型关键字和CTS类型的关系

int Age = 10;
System.Int32 Count = 20;

我们知道,CTS中的类型只有值类型和引用类型两种,包括.NET框架预定义的BCL类库和我们自定义的类、接口等,如图4-4所示。

下面我们从值类型和引用类型两方面来分析C#语言的内置类型。

1. 内置的值类型

首先通过一幅图来看看C#语言中的值类型包含哪些类型,如图4-5所示。

由图4-5可以看出,值类型主要由两大类型组成:结构类型和枚举类型。而我们平时常用的数值型、布尔型都是结构类型,其中数值型又包括:整型、浮点型和十进制型,下面将分别介绍。

正确的使用类型是很重要的,我们先通过表4-3了解整型所包含的类型,以及它们的取值范围和长度信息,然后对每个类型逐一介绍。

(1)sbyte

sbyte关键字表示整数数据类型。

声明和使用sbyte类型的变量:

sbyte val = 100;
(2)byte

byte关键字表示整数数据类型。

声明和使用byte类型的变量:

byte val = 100;
(3)char

char关键字用于声明一个Unicode字符。Unicode字符是16位字符,用于表示世界上已知的绝大多数书面语言。

char关键字的使用举例如下:

char[] chars = new char[4];
chars[0] = 'X'; // 字符
chars[1] = '\x0058'; // 16进制
chars[2] = (char)88; // 从数值型转换
chars[3] = '\u0058'; // Unicode

foreach (char c in chars)
{
    Console.Write(c + " ");
}

上述代码的输出结果为:X X X X

(4)short

short关键字表示整数数据类型。

short的用法如下:

short val = 12345;
(5)ushort

ushort关键字表示整数数据类型。

ushort的用法如下:

ushort ushortVal = 65535;
(6)int

int关键字表示整数数据类型。

int的用法如下:

int iVal = 65535;
(7)uint

uint关键字表示整数数据类型。

uint的用法如下:

uint theUint = 967295;
(8)long

long关键字表示整数数据类型。

long的声明有如下几种方式:

long longValue1 = 4294967296;
long longValue2 = 4294967296L; // 后缀'L'
long longValue3 = 4294967296l; // 后缀'l',和大写'L'等价

注意虽然后缀使用大写的"L"和小写的"l"均可,但小写的"l"易和数字"1"混淆,因此为了不引起混淆,建议使用大写的"L"做后缀。

(9)ulong

ulong关键字表示整数数据类型。

ulong的用法如下:

ulong uLong = 9223372036854775808;

则其类型为以下类型中可表示其值的第一个类型:intuintlongulong。在上面的示例中,它是ulong类型。

还可根据以下规则使用后缀指定文字类型:

  1. 如果使用Ll,那么根据整数的大小,可以判断出其类型为long还是ulong

  2. 如果使用Uu,那么根据整数的大小,可以判断出其类型为uint还是ulong

  3. 如果使用ULulUluLLUluLulU,则整数的类型为ulong

2. 浮点型

浮点型分为单精度浮点数(float)和双精度浮点数(double),如表4-13所示。

(1)float

float关键字表示存储32位浮点值的简单类型。

默认情况下,赋值运算符右侧的实数被视为double类型。因此,应使用后缀fF初始化浮点型变量,如以下示例所示:

float x = 3.14F;

注意:如果在以上声明中不使用后缀,则会因为你试图将一个double值存储到float变量中而发生编译错误:Literal of type double cannot be implicitly converted to type 'float'; use an 'F' suffix to create a literal of this type.

(2)double

double关键字表示存储64位浮点值的简单类型。

默认情况下,赋值运算符右侧的实数被视为double。但是,如果希望整数被视为double,请使用后缀dD,例如:

double x = 10d;

3. 十进制型

表4-16给出了十进制型的大致范围和精度。

decimal关键字表示高精度的十进制数数据类型。

如果希望实数被视为decimal类型,请使用后缀mM,例如:

decimal myMoney = 1023.5m;

注意:如果没有后缀m,数字将被视为double类型,从而导致编译器错误。

4. 布尔型

bool关键字是System.Boolean的别名,用于声明变量来存储布尔值truefalse

注意:如果需要一个可以为null的布尔型变量,可以使用bool?

可将布尔值赋给bool变量。也可以将计算为bool类型的表达式赋给bool变量,如下所示。

bool isArrived = false;
int speed = 120;
bool isOverSpeed = speed > 100;

if (!isArrived && isOverSpeed)
{
    Console.WriteLine("你超速了!请注意安全!");
}

5. 自定义结构类型

struct类型是一种值类型,如果需要一个用于存储数据并且数据量较小的类型时,通常使用结构类型,例如,矩形的坐标或库存商品的特征。下面的示例显示了一个简单的结构声明。

public struct Point
{
    public int X;
    public int Y;
}

6. BigInteger和Complex

这两个类型都是在.NET 4中新增的,它们位于System.Numerics命名空间。表4-18是对它们的说明。

(1)BigInteger

BigInteger类型是不可变类型,代表一个任意大的整数,其值在理论上已没有上部或下部的界限。此类型不同于.NET Framework中的其他整型,后者已通过其MinValueMaxValue属性指示了一个范围。因为它没有没有上限或下限,对于导致BigInteger值增长过大的任何操作都会引发内存溢出异常------OutOfMemoryException

代码清单4-8 是使用了BigInteger类型的示例代码。

代码清单4-8 BigInteger的使用示例

using System;

namespace ProgrammingCSharp4
{
    class BigIntegerSample
    {
        static void Main(string[] args)
        {
            System.Numerics.BigInteger googol = System.Numerics.BigInteger.Pow(10, 100);
            Console.WriteLine(googol.ToString());
        }
    }
}

BigInteger.Pow 是 System.Numerics.BigInteger 类型提供的一个静态方法,用于计算一个大整数的幂(即一个数自乘若干次的结果)。

上述代码的运行结果如所示:

10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

请按任意键继续......

要使用BigInteger类,需要手动添加对System.Numerics的引用,如图4-6所示。

(2)Complex

Complex表示一个复数,我们知道,复数由实数部分和虚数部分组成。在实例化和操作复数时,Complex类型使用笛卡尔坐标系统(实数,虚数)。一个复数可以表示为一个二维坐标系中的某个点。复数的实数部分位于x轴(水平轴),虚数部分位于y轴(垂直轴)。

代码清单4-9 是使用了Complex类型的示例代码。

代码清单4-9 Complex类型示例代码

using System;
using System.Numerics;

namespace ProgrammingCSharp4
{
    class BigIntegerSample
    {
        static void Main(string[] args)
        {
            var z1 = new Complex(6, 6);
            var z2 = new Complex(8, 8);
            var r1 = Complex.Add(z1, z2);
            var r2 = Complex.Subtract(z1, z2);
            var r3 = Complex.Multiply(z1, z2);
            var r4 = Complex.Divide(z1, z2);

            Console.WriteLine("Z1+Z2: " + r1);
            Console.WriteLine("Z1-Z2: " + r2);
            Console.WriteLine("Z1×Z2: " + r3);
            Console.WriteLine("Z1÷Z2: " + r4);
        }
    }
}

上述代码的运行结果如下:

Z1+Z2:(14,14)
Z1-Z2:(-2,-2)
Z1×Z2:(0,96)
Z1÷Z2:(0.75,0)
请按任意键继续......

7. 内置的引用类型

引用类型的变量又称为对象,存储的是对实际数据的引用。引用类型的变量存储在托管栈中,而实际的数据存储在托管堆中,引用类型主要成员如下,如图4-7所示。

1. 类

类是C#中最重要的类型,它使用关键字class进行声明。关于类的更多内容将会在后续文章介绍,这里只简单介绍类的声明和实例化。

我们定义一个类,用以描述现实中的矩形,如图4-8所示。矩形本身就是一个类,它具有如下几个特征:

  1. 长度

  2. 宽度

  3. 位置(这里通过左上角的坐标来表示)

通过确定这几个特征就可以确定一个矩形的长、宽以及在某一个平面上的位置,从而得到一个具体的矩形。长度、宽度以及位置不同的矩形有无穷多,所以我们说,矩形是一个类,而这三个要素所确定的每一个具体的矩形就是类的一个实例(或者叫做对象),如图4-9所示。实例4是一种特殊的矩形------正方形。至于是否应该将正方形归类到矩形,从面向对象软件设计的角度讲是有争议的,详情可以参考设计模式中的"里氏代换原则"。

下面,我们看看类相关的语法。首先,我们使用如下语法声明一个类:

class TestClass
{
    // 方法、属性、字段、事件、委托
    // 以及内部类等,这些都是类的主体.
}

例如,我们声明一个SampleObject的类,它有一个字符串类型的sampleValue字段,代码如下:

class SampleObject
{
    public string sampleValue;
}

一般情况都需要对类进行实例化,我们可以使用new关键词对类进行实例化,例如:

SampleObject sampleObject = new SampleObject();
sampleObject.sampleValue = "sampleValue's scope";
2. 接口

一个有关程序设计的最佳实践,就是要求面向接口编程,这样可以降低程序各部分间的耦合度。那么什么是接口呢?接口和类有什么区别?实现了接口的类必须实现接口规定的方法、属性等,可以说接口是一种约定,甚至是一种规定。接口和类的重要区别有如下两点:

  1. 接口可以继承多个基接口,而类只能继承一个类,但可以实现多个接口;

  2. 接口只能包含签名,不能含有实现,类无此限制。接口能包含下列成员的签名:

    1. 方法

    2. 属性

    3. 事件

    4. 索引器

如图4-10所示,接口定义了两个方法:方法1和方法2,那么实现该接口的两个类都必须提供这两个方法的实现。除此之外,每个实现类都可以有独立的其他方法实现,接口对此并无限制,例如第一个类除了实现方法1和方法2之外还有方法3,另一个实现类还有方法4。

接下来我们定义一个接口,并且实现它:

interface TestInterface
{
    void TestMethod();
}

class TestClass : TestInterface
{
    public void TestMethod()
    {
        Console.WriteLine("Hello world!");
    }
}
3. 委托

委托类似C++中的函数指针,但它是类型安全的,也就是说它能够引用函数。每一个委托都有一个签名,可以使用delegate关键字来声明一个委托。如图4-11所示,委托引用了方法1、方法2等,调用委托就相当于调用它所引用的方法1、方法2等,并且调用的顺序是按方法出现在委托中的顺序。

下面,我们通过以下代码来看一个委托实例:

class TestDelegate
{
    delegate void OneDelegate();

    void method1()
    {
        Console.WriteLine("I'm method1!");
    }

    void method2()
    {
        Console.WriteLine("I'm method2!");
    }

    void Main()
    {
        OneDelegate oneDelegate = method1;
        oneDelegate += method2;
        oneDelegate();
    }
}
4. 字符串

字符串可以说是使用最频繁也是最常见的类型了,想必大家对它并不陌生。C#语言中的字符串类型是string,它是.NET Framework中String的别名。string类型表示零或更多Unicode字符(char)组成的序列,既然是序列,也就意味着字符串是一个字符数组(char[]),你可以使用[]运算符来访问string中的每个字符。可以使用如下几种方法声明并初始化一个字符串类型的变量:

string str1 = "hello world!";
var str2 = "hello world!";
5. 数组

数组是一种数据结构,它包含若干相同类型的变量,使用如下语法进行声明:

type[] arrayName;

这里的type可以是值类型,也可以是引用类型。其中,arrayName是变量名,它是个标识符。需要注意的是,声明数组时,方括号"[]"必须在类型type后面,而不能在标识符后面,这一点和C语言不同。包含在数组中的变量叫做元素,元素的类型就是数组的类型。下面我们看看如何去读取数组中的元素,其语法是:

type arrayValue = arrayName[index];

这里的index是数组的下标,它从0开始,因此最大值比数组长度少1。举例说明,如果数组有10个元素,那么第一个元素的下标为0,最后一个元素的下标为9,以此类推。

数组示意图如图4-12所示。

仅仅声明还不行,在使用它之前先要进行初始化,语法如下:

type[] arrayName = new type[num];

在上述代码中,声明以后立刻对数组进行了初始化。也可以把声明和初始化分开来做,如:

type[] arrayName;
arrayName = new type[num];

这里的num是指定数组的大小,比如,可以这样声明一个含有10个元素的int型数组,如代码清单4-10所示。

代码清单4-10 数组示例

using System;

namespace ProgrammingCSharp4
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] sampleArray = new int[10];
            for (int i = 0; i < sampleArray.Length; i++)
            {
                Console.WriteLine(sampleArray[i]);
            }
        }
    }
}

这里声明并初始化了一个含有10个元素的数组,运行它,我们会得到如下结果:

0
0
0
0
0
0
0
0
0
0

在声明并初始化数组以后,在对每个元素赋值之前,它们的初始值就是相应类型type的默认值,这里是int类型的默认值0。如果是引用类型的数组,那么相应类型的默认值请参阅表4-1。

下面是另一种类型的初始化方式,如下:

int[] sampleArray = {1, 10, 20, 30, 60};

注意数组的大小一旦确定就无法再进行改变,即增加和减少元素数量都是不允许的。如果声明数组的时候没有指明数组大小,则必须在初始化时进行指定,或通过int[] sampleArray = {1, 10, 20, 30, 60};由编译器自动确定。

6. object类型

C#里的object是.NET框架中Object的别名。在CTS中,所有类型包括:预定义类型、用户自定义类型、引用类型和值类型,都是直接或间接从Object继承的。因此,可以将任何类型的值赋给object类型的变量。

之前的文章提到过,将值类型的变量转换为对象的过程称为"装箱",相反,将对象类型的变量转换为值类型的过程称为"拆箱"。

7. null类型

null关键字代表一个空值,用以表示一个引用没有指向任何对象或数组。它是引用类型变量的默认值。另外,null不可作为一个类型去声明变量,也不能作为一个目标类型以推断某参数的类型。

8. 指针类型

我们知道,指针操作是高效的,但也是不安全的。C#语言也支持指针,但规定只能在一个标记了unsafe的上下文中使用。下述各类型都可以作为指针类型:

  1. sbytebyteshortushortintuintlongulongcharfloatdoubledecimal以及bool

  2. 枚举类型;

  3. 指针类型;

  4. 用户定义的仅包含非托管类型字段的结构类型。

定义指针类型的语法如下:

类型* 指针类型名称;

表4-19是一个定义指针类型的示例。

9. Nullable类型

一个Nullable类型就是基本类型加上一个"是否为null指示器"的合成类型。对于一个类型,如果既可以给它分配一个值,也可以给它分配null引用(表示没有任何值),我们就说这个类型是可空的。因此,可空类型可表示一个值,或表示不存在任何值。例如,类似String的引用类型就是可空类型,而类似Int32的值类型不是可空类型。由于值类型的容量只够表示适合于该类型的值,因此它不可为空。那么该如何理解呢?有些人认为int型变量的值0就表示空,这是不对的,0也是它的值,而并不表示空。我们看看代码清单4-11所示的代码。

代码清单4-11 Nullable类型用法

using System;

namespace ProgrammingCSharp4
{
    class Program
    {
        static void Main(string[] args)
        {
            int? oneValue = null;
            // oneValue = 10;

            if (oneValue.HasValue)
            {
                Console.WriteLine(oneValue.Value);
            }
            else
            {
                Console.WriteLine("oneValue的值为null!");
            }
        }
    }
}

第9行定义的Nullable类型和定义一个非Nullable类型非常类似,不同之处在于类型后的类型修饰符"?"

另外,这里我们为oneValue变量赋予了初始值null,这也是不同于非Nullable类型的地方。

第12行中Nullable类型的HasValue属性用来判断是否有值存储,如果为true则表示有值,即不为null;为false则表示没有值,此时如果尝试获得变量的值时会产生一个异常:

System.InvalidOperationException:可为空的对象必须具有一个值。

第13行中Nullable类型的Value属性存储赋予变量的值。

请大家先运行代码清单4-9,然后再将第10行前的注释符号"//"去掉再运行,对比两次运行的结果。

10. dynamic类型

dynamic类型是C# 4.0引入的全新类型,它允许其操作略过编译期类型检查,而在运行时处理。dynamic类型简化了对COM API的调用(例如对Office组件的COM Interop调用),增强了对动态语言的支持(例如IronPython库),简化了对于HTML文档对象模型(DOM)的访问。

dynamic类型在绝大多数情况下和object类型相似,不同点在于,编译器对于包含了dynamic类型的表达式不做进一步解析和类型检查。编译器将这些信息收集到一起,用于在运行时鉴定操作。实际上,dynamic类型的变量被编译成object类型的变量,因此,dynamic类型只存在于编译期,而运行时并不存在,如图4-13所示。

我们一起来看如下的示例,如代码清单4-12所示。

代码清单4-12 dynamic类型用法

using System;

namespace ProgrammingCSharp4
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic dyn = 1;
            object obj = 1;

            Console.WriteLine(dyn.GetType());
            Console.WriteLine(obj.GetType());

            // dyn += 1; // 编译通过
            // obj += 1; // 编译失败
        }
    }
}

输出结果为:

System.Int32
System.Int32

dyndynamic类型变量,在编译期并不知道它的类型,因此,虽然知道1是System.Int32类型,但因dynamic类型变量在编译期并不解析也不做类型检查,因此1的类型信息被编译期收集起来,在运行时根据该信息确定dynSystem.Int32类型的变量,此时dyn就已经不再是dynamic类型的变量了,而是System.Int32类型,因此才会有上述结果。图4-14说明了动态类型在编译期和运行时的类型。

我们再做个实验,首先将第15行的注释去除,然后按Shift+F6进行编译,此时应该顺利编译通过;然后将第16行的注释去除[1],再编译,这时会产生一个编译错误:运算符"+="无法应用于"object"和"int"类型的操作数信息显示:"+="操作符无法应用于object类型和int类型,obj必须强制转换为int型的变量。为什么dyn变量可以呢?因为编译期不对dynamic变量进行类型检查,因此在编译期dyn很容易就过编译器这一关了,到了运行时就更不用说了,那是dynamic的天下,运行时判定dyn变量为System.Int32类型,因此执行"+="运算是完全合法的。

使用dynamic类型要注意以下几个问题:

  1. 由于dynamic类型的变量在设计时类型是未知的,因此你无法看到Visual Studio对dynamic类型变量的成员进行自动提示,因为无法提示;

  2. 由于dynamic类型变量的具体类型要在运行时才能确定,因此你对该变量的成员调用必须是正确的,如果调用了变量没有的属性或方法,将会产生异常。删掉行首的"//"符号。

11. 进阶阅读:关于动态语言运行时

DLR是Dynamic Language Runtime的简称,是构建于CLR之上的一系列类库,以提供对动态语言的支持。.NET CLR的核心价值之一就是支持多语言并允许它们之间互操作。动态语言在近些年已变得日益流行,因此人们希望使用自己喜欢的动态语言,并且在不失去卓越的.NET互操作性的前提下构建应用程序。DLR让这种想法成为现实。

DLR也支持.NET平台上现有的语言。它为静态类型的语言,例如C#,增加了动态的特性。使用C# 4.0,可以很方便地支持动态对象,如COM Interop调用、HTML DOM或.NET反射。

动态语言可以在运行时识别一个对象的类型,然而,在静态类型语言中,例如C#,你必须在设计时就指定对象的类型。动态语言有很多,例如:JavaScript、PHP、Ruby、Python以及Groovy等。在Visual Studio 2010中,DLR为C#语言引入了新的dynamic对象,为它增加对动态特性的支持,从而允许与动态语言之间的互操作,DLR的架构如图4-15所示。

从图4-6可看出,DLR使用联接器(Object Binder、JavaScriptBinder、Python Binder等)来与除.NET框架之外的其他基本设施和服务进行通信,例如Silverlight、COM以及Python、Ruby等。联接器封装了语言的语义,并详细说明了在调用点(Call Site)中如何通过使用表达式树(Expression Tree)来执行操作。这让动态语言和使用DLR的静态语言得以共享类库,并可以访问所有DLR支持的技术。

DLR还帮助建立类库以支持动态操作。例如,如果有一个使用XML或者JavaScript Object Notation(JSON)对象的库,那么对于使用DLR的语言来说就是一些动态对象,这可以让类库的用户以更简单、更自然的方式来和这些对象进行交互。

例如,你可能使用如下C#语句来让一个位于XML文件中的计数器递增:

Scriptobj.SetProperty("Count", ((int)GetProperty("Count")) + 1);

如果使用DLR,那么下面的代码和上述代码是等价的:

scriptobj.Count += 1;

总结一下,DLR的目标就是简化如下操作:

  1. 移植动态语言到.NET平台;

  2. 为现有语言添加动态特性;

  3. 开发支持动态操作的类库;

  4. 在应用和框架中使用动态语言。

这里我们简单介绍了DLR,后面的文章会对它进行详细讲解,C# 4.0的一个关键特性就是通过使用DLR引入的动态特性,这种特性使得语法进一步简化,代码更加直观和自然。因此,掌握和运用C#的动态特性很重要。

标签:变量,C#,数据类型,System,int,类型
From: https://blog.csdn.net/weixin_44643352/article/details/145114055

相关文章

  • 利用 LangChain 与 Eden AI 模型进行交互的完整指南
    利用LangChain与EdenAI模型进行交互的完整指南EdenAI是一个颠覆性的AI平台,通过统一多个提供商的优秀AI模型,简化了开发者的工作流。凭借单一API,开发者可以快速将强大的AI功能整合到生产环境中,轻松实现多样化的AI能力。本文将介绍如何使用LangChain与Eden......
  • CKA | Docker容器技术概述
    往期文章推荐【新版】容器&Kubernetes认证管理员(CKA)课程介绍k8s-CKS认证课程介绍【K8s】Kubernetes词汇表什么是Docker容器?3个管理多k8s集群实用工具K8S-CKA课程试听:Container概述CKA课程|Docker容器技术概述 今日分享内容CKA第一节课  目录1......
  • mysql、oracle、sqlserver的区别
    一、保存数据的持久性:        MySQL:是在数据库更新或者重启,则会丢失数据。                Oracle:把提交的sql操作线写入了在线联机日志文件中,保持到了磁盘上,可以随时恢复。                SqlServer:2014之后,也拥有了完全持久和延......
  • React源码解析(1): JSX语法与react项目渲染过程
    好家伙 0.前言由于工作的需要,我不得不入手了react的全家桶,曾经我的主要技术栈是vue。从vue转到react,一开始我感到非常不适应,jsx的语法的不了解,reacthooks的使用方式,react路由的配置。。。这一度让我十分难受但在熟悉一段时间后,我逐渐领略到react的魅力,灵活的状态管理,渲染速......
  • 长脸了!国产机器人闪耀CES 2025
    在CES2025展会上,众多国内机器人企业积极参展,展示各种各样的机器人产品,如智元远征A2、星动纪元Star1、银河通用G1、宇树H1及小鹏Iron等,展现了中国机器人产业在国际舞台上令人瞩目的发展成果。丰富的国产机器人类型展示人形机器人展示伟景智能发布的晓唯人形机器人,搭载了ViEy......
  • 《浪漫沙加2:七英雄的复仇》游戏启动时报错提示“找不到facesdk.dll”文件的原因和处理
    对于众多游戏爱好者而言,《浪漫沙加2:七英雄的复仇》无疑是一款备受期待、渴望沉浸其中的佳作。然而,不少玩家在满心欢喜准备启动游戏时,却遭遇了令人沮丧的报错提示——“找不到facesdk.dll”文件,这一状况瞬间打破了游戏的美好憧憬,探寻背后原因与处理方案势在必行。报错提示......
  • 如何贡献开源项目LangChain:完整指南
    LangChain是一个快速发展的开源项目,旨在构建强大的AI应用程序框架。作为一名开发者或技术爱好者,你或许希望为这个项目贡献力量,无论是开发新功能、修复bug、改进文档,还是参与讨论和设计。这篇文章将详细介绍如何高效地加入LangChain的开发与贡献,帮助你事半功倍。1.......
  • JavaScript与服务器端框架Flask
    JavaScript与服务器端框架Flask基本概念和作用说明示例一:设置基本的Flask环境示例二:使用JavaScript发起请求功能使用思路及代码示例示例三:处理POST请求示例四:表单验证与反馈开发经验分享在现代Web开发中,前端和后端的紧密结合对于创建高效、响应迅速的应用程序至关......
  • keycloak~巧用client-scope实现token字段和userinfo接口的授权
    keycloak中的client-scope允许你为每个客户端分配scope,而scope就是授权范围,它直接影响了token中的内容,及userinfo端点可以获取到的用户信息,这块我们可以通过自定义scope/mapper,来实现粒度的控制,并且这个mapper可以控制添加到token,或者添加到userinfo端点,这两块配置也是独立的,下面......
  • 在OERV也可以玩MC(上)
     最近发现一个比较有意思的事情,原来HMCL这个项目也移植到RISC-V上了,之前一直没有发现,因此在OERV(openEulerRISC-V的简称)玩MC也是可以的了。首先,HMCL是一款功能丰富的Minecraft启动器,旨在提升玩家的游戏体验,为Minecraft玩家提供了更好的管理和启动游戏的工具。但是部署的过程......