编程技术是改变世界的力量。
本站
当前位置:网站首页 > 后端语言 > 正文

C#数据类型:值类型和引用类型,类型转换,字符串类型的玩法

gowuye 2024-05-16 14:22 3 浏览 0 评论

C#是一种强类型语言,每个变量和常量都有一个类型,每个表达式也有一个类型。C#提供了多种数据类型,包括内置的数值类型、布尔类型、字符类型,以及用户自定义的结构类型、枚举类型、类类型、接口类型等。本文将介绍C#中的三个重要话题:值类型和引用类型的区别,类型转换的方法和注意事项,以及字符串类型的特点和用法。

值类型和引用类型的区别

值类型和引用类型是C#中两个主要的类别。值类型的变量包含了类型的实例,而引用类型的变量包含了对类型实例的引用。这意味着在赋值或传递参数时,值类型会复制实例,而引用类型只会复制引用。例如:

// 值类型

int x = 10; // x包含了10这个值

int y = x; // y也包含了10这个值,x和y是独立的

y = 20; // y的值改变为20,不影响x

Console.WriteLine(x); // 输出10

Console.WriteLine(y); // 输出20

// 引用类型

string s1 = "Hello"; // s1包含了对"Hello"这个字符串实例的引用

string s2 = s1; // s2也包含了对"Hello"这个字符串实例的引用,s1和s2指向同一个实例

s2 = "World"; // s2的引用改变为指向"World"这个字符串实例,不影响s1

Console.WriteLine(s1); // 输出Hello

Console.WriteLine(s2); // 输出World

值类型可以分为以下几种:

- 结构类型:用于封装数据和相关功能,例如内置的数值类型、字符类型、布尔类型等,以及用户自定义的结构。

- 枚举类型:由一组命名常数定义,表示一个选择或选择组合,例如System.DayOfWeek。

- 可为null值类型:表示其基础值类型的所有值及额外的null值,例如int?。

引用类型可以分为以下几种:

- 类类型:用于定义对象,包含数据成员和方法成员,例如System.String、System.Object等,以及用户自定义的类。

- 接口类型:用于定义一组抽象的方法和属性规范,由实现它们的类提供具体功能,例如System.IDisposable、System.IComparable等。

- 数组类型:用于存储同一种元素类型的固定长度或可变长度序列,例如int[]、string[,]等。

- 委托类型:用于表示可执行代码的引用,可以作为参数传递或作为返回值返回,例如System.Action、System.Func等。

## 类型转换的方法和注意事项

在C#中,有时需要将一个数据类型转换为另一个数据类型。例如,在数学运算中需要将整数转换为浮点数,在多态性中需要将基类转换为派生类,在字符串处理中需要将数字转换为字符串等。C#提供了以下几种方法进行数据转换:

- 隐式转换:由于这种转换始终会成功且不会导致数据丢失,因此无需使用任何特殊语法。示例包括从较小整数类型到较大整数类型的转换以及从派生类到基类的转换的情况。例如:

// 隐式转换

int i = 10; // i是int类型

long l = i; // l是long类型,可以存储int类型的任何值

Animal a = new Dog(); // a是Animal类型,Dog是Animal的派生类

// 显式转换(强制转换)

double d = 3.14; // d是double类型

int j = (int)d; // j是int类型,需要强制转换,可能丢失小数部分

Dog d = (Dog)a; // d是Dog类型,需要强制转换,可能在运行时失败

-用户定义的转换:用户可以定义自己的类型之间的隐式转换和显式转换,通过使用implicit和explicit关键字来重载转换运算符。例如:

// 用户定义的转换

class Celsius

{

public double Temperature { get; set; }

public Celsius(double temp) { Temperature = temp; }

// 隐式转换从Celsius到Fahrenheit

public static implicit operator Fahrenheit(Celsius c)

{

return new Fahrenheit((9.0 / 5.0) * c.Temperature + 32);

}

// 显式转换从Celsius到Kelvin

public static explicit operator Kelvin(Celsius c)

{

return new Kelvin(c.Temperature + 273.15);

}

}

class Fahrenheit

{

public double Temperature { get; set; }

public Fahrenheit(double temp) { Temperature = temp; }

}

class Kelvin

{

public double Temperature { get; set; }

public Kelvin(double temp) { Temperature = temp; }

}

class TestTemperature

{

static void Main()

{

Celsius c = new Celsius(37);

Fahrenheit f = c; // 隐式转换

Kelvin k = (Kelvin)c; // 显式转换

Console.WriteLine(#34;Celsius: {c.Temperature}, Fahrenheit: {f.Temperature}, Kelvin: {k.Temperature}");

}

}

// 输出:Celsius: 37, Fahrenheit: 98.6, Kelvin: 310.15


-使用帮助类进行转换:如果要在不兼容的类型之间进行转换,例如整数和日期,或者十六进制字符串和字节数组,可以使用一些帮助类来实现。例如System.BitConverter, System.Convert, System.Int32等。例如:

// 使用帮助类进行转换

int n = 1234567890;

byte[] bytes = BitConverter.GetBytes(n); // 将整数转换为字节数组

string hex = BitConverter.ToString(bytes); // 将字节数组转换为十六进制字符串

Console.WriteLine(hex); // 输出:D2-02-96-49

string s = "123";

int m = Convert.ToInt32(s); // 将字符串转换为整数

Console.WriteLine(m); // 输出:123

string t = "FF";

int x = Int32.Parse(t, System.Globalization.NumberStyles.HexNumber); // 将十六进制字符串解析为整数

Console.WriteLine(x); // 输出:255

在进行类型转换时,需要注意以下几点:

- 不要假设类型转换总是成功的,要使用try-catch语句来处理可能发生的异常,或者使用TryParse等方法来尝试转换并检查返回值。

- 不要滥用隐式转换和用户定义的转换,以免造成代码的可读性和可维护性下降。

- 不要忽略类型转换可能导致的精度损失或溢出问题,要根据实际情况选择合适的数据类型和转换方式。

- 不要对null值进行类型转换,否则会引发NullReferenceException异常。

## 字符串类型的特点和用法

字符串是值为文本的String类型对象。文本在内部存储为Char对象的依序只读集合。在C#字符串末尾没有null终止字符;因此,一个C#字符串可以包含任何数量的嵌入的null字符('\0')。字符串的Length属性表示其包含的Char对象数量,而非Unicode字符数。要访问字符串中的各个Unicode码位,请使用StringInfo对象。

string与System.String

在C#中,string关键字是String的别名。因此,String和string是等效的(虽然建议使用提供的别名string),因为即使不使用using System;,它也能正常工作。String类提供了安全创建、操作和比较字符串的多种方法。此外,C#语言重载了部分运算符,以简化常见字符串操作。

声明和初始化字符串

可以使用各种方法声明和初始化字符串,如以下示例中所示:

// 声明但不初始化

string message1;

// 初始化为null

string message2 = null;

// 初始化为空字符串

// 使用Empty常量而不是字面量""

string message3 = System.String.Empty;

// 使用普通字符串字面量初始化

string oldPath = "c:\\Program Files\\Microsoft Visual Studio 8.0";

// 使用逐字字符串字面量初始化

string newPath = @"c:\Program Files\Microsoft Visual Studio 9.0";

// 如果你喜欢,可以使用System.String

System.String greeting = "Hello World!";

// 在局部变量(即方法体内)中

// 你可以使用隐式类型

var temp = "I'm still a strongly-typed System.String!";

// 使用const string来防止'message4'被

// 用来存储另一个字符串值

const string message4 = "You can't get rid of me!";

// 只有在从char*、char[]或sbyte*创建字符串时才使用String构造函数。

// 有关详细信息,请参阅System.String文档。

char[] letters = { 'A', 'B', 'C' };

string alphabet = new string(letters);

不要使用new运算符创建字符串对象,除非使用字符数组初始化字符串。使用Empty常量值初始化字符串,以新建字符串长度为零的String对象。长度为零的字符串文本表示法是“”。通过使用Empty值(而不是null)初始化字符串,可以减少NullReferenceException发生的可能性。尝试访问字符串前,先使用静态IsNullOrEmpty(String)方法验证字符串的值。

字符串的不可变性

字符串对象是“不可变的”:它们在创建后无法更改。看起来是在修改字符串的所有String方法和C#运算符实际上都是在新的字符串对象中返回结果。在下面的示例中,当s1和s2的内容被串联在一起以形成单个字符串时,两个原始字符串没有被修改。+=运算符创建一个新的字符串,其中包含组合的内容。这个新对象被分配给变量s1,而分配给s1的原始对象被释放,以供垃圾回收,因为没有任何其他变量包含对它的引用。

// 声明但不初始化

string message1;

// 初始化为null

string message2 = null;

// 初始化为空字符串

// 使用Empty常量而不是字面量""

string message3 = System.String.Empty;

// 使用普通字符串字面量初始化

string oldPath = "c:\\Program Files\\Microsoft Visual Studio 8.0";

// 使用逐字字符串字面量初始化

string newPath = @"c:\Program Files\Microsoft Visual Studio 9.0";

// 如果你喜欢,可以使用System.String

System.String greeting = "Hello World!";

// 在局部变量(即方法体内)中

// 你可以使用隐式类型

var temp = "I'm still a strongly-typed System.String!";

// 使用const string来防止'message4'被

// 用来存储另一个字符串值

const string message4 = "You can't get rid of me!";

// 只有在从char*、char[]或sbyte*创建字符串时才使用String构造函数。

// 有关详细信息,请参阅System.String文档。

char[] letters = { 'A', 'B', 'C' };

string alphabet = new string(letters);

字符串的比较和排序

字符串的比较和排序是一个复杂的话题,因为不同的场景可能需要不同的规则和逻辑。在C#中,有两种基本的比较方式:序号比较和语义比较。

序号比较是按照字符串中每个字符的二进制值进行比较,不考虑语言或区域性的规则。序号比较通常用于测试字符串是否相等,或者在不需要区分大小写或区域性的情况下对字符串进行排序。序号比较可以分为区分大小写和不区分大小写两种。

语义比较是按照字符串中每个字符的语言含义进行比较,考虑区域性或文化的规则。语义比较通常用于对字符串进行排序,或者在需要区分大小写或区域性的情况下测试字符串是否相等。语义比较可以分为当前区域性和固定区域性两种。

C#提供了多种方法来进行字符串的比较和排序,例如:

- String.Equals方法用于测试两个字符串是否相等,可以指定StringComparison参数来选择不同的比较方式。

- String.Compare方法用于比较两个字符串在排序顺序中的相对位置,返回一个整数值,可以指定StringComparison参数来选择不同的比较方式。

- String.CompareTo方法用于比较当前字符串对象与另一个字符串或对象的字符串表示形式,在排序顺序中的相对位置,返回一个整数值。

- String.Contains方法用于判断当前字符串是否包含指定的子字符串,返回一个布尔值。

- String.IndexOf方法用于查找指定字符或子字符串在当前字符串中第一次出现的索引位置,返回一个整数值,可以指定开始搜索的位置和StringComparison参数来选择不同的比较方式。

- String.LastIndexOf方法用于查找指定字符或子字符串在当前字符串中最后一次出现的索引位置,返回一个整数值,可以指定开始搜索的位置和StringComparison参数来选择不同的比较方式。

- String.StartsWith方法用于判断当前字符串是否以指定的子字符串开头,返回一个布尔值,可以指定StringComparison参数来选择不同的比较方式。

- String.EndsWith方法用于判断当前字符串是否以指定的子字符串结尾,返回一个布尔值,可以指定StringComparison参数来选择不同的比较方式。

下面是一些示例代码:

// 序号比较

string s1 = "Hello";

string s2 = "hello";

bool b1 = s1.Equals(s2); // false

bool b2 = s1.Equals(s2, StringComparison.Ordinal); // false

bool b3 = s1.Equals(s2, StringComparison.OrdinalIgnoreCase); // true

int i1 = s1.CompareTo(s2); // -32

int i2 = String.Compare(s1, s2, StringComparison.Ordinal); // -32

int i3 = String.Compare(s1, s2, StringComparison.OrdinalIgnoreCase); // 0

// 语义比较

string s3 = "Stra?e";

string s4 = "Strasse";

bool b4 = s3.Equals(s4); // false

bool b5 = s3.Equals(s4, StringComparison.CurrentCulture); // false

bool b6 = s3.Equals(s4, StringComparison.InvariantCulture); // true

int i4 = s3.CompareTo(s4); // 1

int i5 = String.Compare(s3, s4, StringComparison.CurrentCulture); // 1

int i6 = String.Compare(s3, s4, StringComparison.InvariantCulture); // 0

// 其他方法

string s5 = "Hello World";

bool b7 = s5.Contains("World"); // true

int i7 = s5.IndexOf('o'); // 4

字符串的拼接和分割

字符串的拼接和分割是指将多个字符串连接成一个字符串,或者将一个字符串按照一定的规则切分成多个子字符串。在C#中,有多种方法可以实现字符串的拼接和分割,例如:

- +和+=运算符用于简单地将两个或多个字符串连接起来,例如:

string s1 = "Hello";

string s2 = "World";

string s3 = s1 + " " + s2; // "Hello World"

s1 += " "; // "Hello "

s1 += s2; // "Hello World"

- 字符串插值用于在一个字符串字面量中插入其他变量或表达式的值,例如:

string name = "Alice";

int age = 25;

string s4 = #34;Hello, {name}. You are {age} years old."; // "Hello, Alice. You are 25 years old."

- String.Format方法用于根据指定的格式字符串和参数列表创建一个新的字符串,例如:

string name = "Bob";

int age = 30;

string s5 = String.Format("Hello, {0}. You are {1} years old.", name, age); // "Hello, Bob. You are 30 years old."

- StringBuilder类用于在循环或其他性能敏感的场景中动态地构建字符串,例如:

StringBuilder sb = new StringBuilder();

for (int i = 0; i < 10; i++)

{

sb.Append(i.ToString());

}

string s6 = sb.ToString(); // "0123456789"

- String.Concat方法用于将一个字符串数组或集合中的所有元素连接成一个字符串,例如:

string[] words = {"The", "quick", "brown", "fox"};

string s7 = String.Concat(words); // "Thequickbrownfox"

- String.Join方法用于将一个字符串数组或集合中的所有元素使用指定的分隔符连接成一个字符串,例如:

string[] words = {"The", "quick", "brown", "fox"};

string s8 = String.Join(" ", words); // "The quick brown fox"

- String.Split方法用于将一个字符串按照指定的字符数组或字符串数组作为分隔符切分成一个子字符串数组,例如:

string s9 = "The quick brown fox jumps over the lazy dog.";

string[] words = s9.Split(' '); // {"The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog."}

string[] sentences = s9.Split('.'); // {"The quick brown fox jumps over the lazy dog", ""}

相关推荐

R语言数据挖掘实践——支持向量机的常用函数
R语言数据挖掘实践——支持向量机的常用函数

e1071包是R语言中用于支持向量机建模与分析的软件包,其主要用于支持向量机的模型构建,提供核心函数svm()来建立支持向量机的基础模型,并且可辅助使用pred...

2024-05-18 12:15 gowuye

R数据分析:如何做聚类分析,实操解析
R数据分析:如何做聚类分析,实操解析

Clusteringisabroadsetoftechniquesforfindingsubgroupsofobservationswi...

2024-05-18 12:14 gowuye

用R语言做数据分析——马赛克图
用R语言做数据分析——马赛克图

到目前为止,我们已经学习了许多可视化定量或连续型变量间关系的方法。但如果变量是类别型的呢?若只观察单个类别型变量,可以使用柱状图或者饼图;若存在两个类别型变量,...

2024-05-18 12:14 gowuye

用R语言做数据分析——方差分析基本概论
用R语言做数据分析——方差分析基本概论

在实际工作中,影响一件事的因素是很多的,我们总是希望通过各种试验来观察各种因素对试验结果的影响。例如,不同的生产厂家、不同的原材料、不同的操作规程,以及不同的技...

2024-05-18 12:14 gowuye

R语言数据分析实战:数据清洗与可视化
R语言数据分析实战:数据清洗与可视化

《R语言数据分析实战:数据清洗与可视化》是一本深入浅出的实践指南,专为对数据分析感兴趣的读者精心编撰。本书旨在帮助读者掌握R语言这一强大的统计分析工具,通过实例...

2024-05-18 12:13 gowuye

用R语言做数据分析——双因素方差分析
用R语言做数据分析——双因素方差分析

在双因素方差分析中,受试者被分配到两因子的交叉类别组中。以基础安装中的Tooth-Growth数据集为例,随机分配60只豚鼠,分别采用两种喂食方法(橙汁或维生素...

2024-05-18 12:13 gowuye

用R语言做数据分析——独立两样本和K样本检验
用R语言做数据分析——独立两样本和K样本检验

coin包简介对于独立性问题,coin包提供了一个进行置换检验的一般性框架,通过这个包,我们可以回答如下问题:响应值与组的分配独立吗?两个数值变量独立吗?两个类...

2024-05-18 12:13 gowuye

用R语言做数据分析——用回归做方差分析
用R语言做数据分析——用回归做方差分析

之前提到方差分析和回归都是广义线性模型的特例,之前文章的所有设计都可以用lm()函数来分析。为了更好地理解输出结果,需要弄明白在拟合模型时,R语言是如何处理类别...

2024-05-18 12:13 gowuye

数据分析R语言——数据结构
数据分析R语言——数据结构

数据分析R语言——数据结构数组数组(array)与矩阵类似,但是维度可以大于2.数组通过array()函数创建。形式如;myarray<-array(v...

2024-05-18 12:13 gowuye

R语言数据挖掘实践——关联分析的常用函数
R语言数据挖掘实践——关联分析的常用函数

arules和arulesViz是R语言中两个专用于关联分析的软件包。其中arules用于关联规则的数字化生成,提供Apriori和Eclat这两种快速挖掘频繁...

2024-05-18 12:12 gowuye

R语言数据挖掘实践——判别分析的常用函数
R语言数据挖掘实践——判别分析的常用函数

判别算法在R语言中实现主要涉及4个软件包中的相关函数,它们依次为MASS、klaR、class和kknn。其中MASS包含有大量实用而先进的统计计数函数及适用数...

2024-05-18 12:12 gowuye

用R语言读取Excel、PDF和JSON文件,终于有人讲明白了
用R语言读取Excel、PDF和JSON文件,终于有人讲明白了

导读:本文将讨论Excel、PDF等文件的读取,以及相应函数的参数设置。作者:刘健邬书豪如需转载请联系华章科技下图总结了主要程序包,希望读者在日常练习和工作中...

2024-05-18 12:12 gowuye

R语言数据挖掘实践——聚类分析的常用函数
R语言数据挖掘实践——聚类分析的常用函数

使用R语言可以轻松实现聚类分析,stats、cluster、fpc和mclust是常用的四个聚类分析软件包。stats主要包含一些基本的统计函数,如用于统计计算...

2024-05-18 12:12 gowuye

用R语言做数据分析——时间序列分类
用R语言做数据分析——时间序列分类

时间序列分类是根据已标注的时间序列建立一个分类模型,然后使用分类模型预测未标记时间序列的类别。从时间序列中抽取出新特征肯呢个有助于提高分类模型的性能。特征提取技...

2024-05-18 12:11 gowuye

一文看懂用R语言读取Excel、PDF和JSON文件(附代码)
一文看懂用R语言读取Excel、PDF和JSON文件(附代码)

导读:本文将讨论Excel、PDF等文件的读取,以及相应函数的参数设置。作者:刘健邬书豪如需转载请联系华章科技下图总结了主要程序包,希望读者在日常练习和工作中...

2024-05-18 12:11 gowuye

取消回复欢迎 发表评论: