/*
类型转换
隐式转换:从类型A到类型B的转换可以在所有情况下进行,进行转换的规则非常简单,可以让编译器执行转换
显示转换:从类型A到类型B的转换只能在某些情况下进行,转换的规则比较负责,应进行某种类型的处理
隐式转换:不需要做任何工作,也不需要编写额外代码
ushort destinationvar;
char sourcevar = 'a';
destinationvar = sourcevar
Console.WriteLine(sourcevar)
Console.WriteLine(destinationvar)
结果就是a和97
这样destinationvar和sourcevar就做了隐式转换没有编写额外代码,但是要注意不同的类型最后展现的结果也会不一样的,因为数据类型不一样了
bool和string没有隐式转换,下面列出一些隐式转换的列表
byte--------------》short,ushort,int,unit,ulong,float,dobule,decimal
sbyte-------------》ushort,int,long,float,dobule,decimal
short-------------》int,long,float,dobule,decimal
ushort------------》int,unit,long,float,dobule,decimal
int---------------》long,float,dobule,decimal
uint--------------》long,ulong,float,dobule,decimal
long--------------》float,dobule,decimal
ulong-------------》float,dobule,decimal
float-------------》dobule
char--------------》ushort,int,unit,long,ulong,float,dobule,decimal
有一个规则,任何类型A,只要起取值范围完全包含在类型B的取值范围内,就可以隐式转换为类型B
显示转换:在明确要求编译器把数值从一种数据类型转换为另一种数据类型时
就是在执行显示转换,因此需要另外编写代码。
byte destinationvar;
short sourcevar = 7;
destinationvar = sourcevar
Console.WriteLine(sourcevar)
Console.WriteLine(destinationvar)
如果编译这段就会产生错误
cannot implicitly convert type 'short' to 'byte'..........
C#编译器可以检测出没有进行显示转换
为了成功编译这段代码需要田间显示转换的代码,最简单的方式把short变量强制转换为byte
强制转换就是强迫数据从一种类型转换为另一种类型,其语法比较简单
<(destinationtype)sourcevar>
就是把sourcevar的值转换为destinationtype
byte destinationvar;
short sourcevar = 7;
destinationvar = (byte)sourcevar
Console.WriteLine(sourcevar)
Console.WriteLine(destinationvar)
现在可以转换是因为7也在byte的范围内(<=255)
纳闷如果超过255该怎么编写?
首先如果依然按照上面的进行转换那么会产生数据丢失的情况
因为已经超过byte最大的保存数值了
这里就要用到两个关键字checked和unchecked,叫做表达式的溢出检查
checked(experssion)
unchecked(experssion)
byte destinationvar;
short sourcevar = 281;
destinationvar = checked((byte)sourcevar)
Console.WriteLine(sourcevar)
Console.WriteLine(destinationvar)
还有一种可以使用convert进行转换
但是需要确定首先转换范围不会溢出
Convert.ToBoolean(val); var---》bool
Convert.ToByte(var); var---》byte
Convert.ToChar(val); var---》char
Convert.ToDecimal(var); var---》decimal
Convert.ToDouble(var); var---》double
Convert.ToInt16(var); var---》short
Convert.ToInt32(var); var---》int
Convert.ToInt64(var); var---》long
Convert.ToSByte(var); var---》sbyte
Convert.ToSingle(var); var---》float
Convert.ToString(var); var---》string
Convert.ToUInt16(var); var---》ushort
Convert.ToUInt32(var); var---》uint
Convert.ToUInt64(var); var---》ulong
其中var可以是大多数变量类型,对于转换总要进行溢出检查
*/
#region
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 变量
{
class Program
{
static void Main(string[] args)
{
short shortresult, shortval = 4;
int integerval = 67;
long longresult;
float floatval = 10.5F;
double doubleresult, doubleval = 99.999;
string stringresult, stringval = "17";
bool boolval = true;
Console.WriteLine("variable conversion example\n");
doubleresult = floatval * shortval;
Console.WriteLine("implicit->double:{0}*{1}->{2}", floatval, shortval, doubleresult);
shortresult = (short)floatval;
Console.WriteLine("explicit->short:{0}->{1}", floatval, shortresult);
stringresult = Convert.ToString(boolval) + Convert.ToString(doubleval);
Console.WriteLine("explicit->string:\"{0}\" + \"{1}\"->{2}",boolval,doubleval,stringresult);
longresult = integerval + Convert.ToInt64(stringval);
Console.WriteLine("mixed->long:{0} + {1} -> {2}", integerval, stringval, longresult);
Console.ReadKey();
}
}
}
#endregion
/*
这个示例包含前面所有的类型转转,例如shortval * floatval
其中一个short值和一个float值相乘,这样的指令中没有指定显示转换,应在可能的情况下
进行隐式转换,在这个示例中唯一有意义的隐式转换是把short转换为float
负责的变量类型:
枚举
有时希望变量提取的是以固定的集合中的值,例如,orientation类型可以存储north,south,east,west
中的一个值此时就可以使用枚举类型注意有一个附加的步骤,不是仅仅声明一个给定类型的变量
而是声明和描述一个用户定义的类型,在声明新类型的变量
定义枚举:
enum <typeName>
{
<value1>,
<value2>,
<value3>,
.
.
.
<valueN>,
}
接着声明新类型的变量
<typeName> <varName>;
并赋值:
<varName> = <typeName><value>
枚举使用一个基本类型来存储,美剧类型可以提取每个值都存储为该基本类型的一个值,默认为int
在枚举的声明中添加类型就可以指定其他基本类型
enum <typeName> : <underlyingType>
{
<value1>,
<value2>,
<value3>,
.
.
.
<valueN>,
}
枚举的基本类型可以是byte,sbyte,short,ushort,int,uint,long,ulong
在默认的情况下每个值都会根据定义的顺序从0开始自动赋值给对应的基本类型
这意味着value1=0,valur2=1可以重写这个赋值过程使用=并指定每个枚举的实际值
没有赋值的任何值都会自动的获得一个初始值,这个初始值就是上一个明确声明值大1
结构
数组
*/
//枚举
namespace my
{
enum orientation : byte
{
north = 1,
south = 2,
east = 3,
west = 4
}
class Program
{
static void Main(string[] args)
{
orientation myDirection = orientation.north;
Console.WriteLine("myDirection = {0}", myDirection);
Console.ReadKey();
}
}
}
namespace my1
{
enum orientation : byte
{
north = 1,
south = 2,
east = 3,
west = 4
}
class Program
{
static void Main(string[] args)
{
byte directionByte;
string directionString;
orientation myDirection = orientation.north;
Console.WriteLine("myDirection = {0}", myDirection);
directionByte = (byte)myDirection;
directionString = Convert.ToString(myDirection);
Console.WriteLine("byte equivalent = {0}", directionByte);
Console.WriteLine("string quivalent = {0}", directionString);
Console.ReadKey();
}
}
}
/*
结构
结构就是由基哥数据组成的数据结构,这些数据可能具有不用类型,
orientation myDirection
double myDirection
使用这样两个变量,是没有错误的,但是在一个地方存储这些信息应该更为简单
定义结构
使用struct
struct <typeName>
{
<memberDeclarations>
}
<memberDeclarations>部分包含变量的声明,其格式与往常一样,每个成员的声明都采用如下形式
<accesslibility> <type> <name>;
要让调用结构的代码访问该结构的数据成员,可以对<accesslibility>使用关键字public,
struct route
{
public orientation direction;
public double distance;
}
定义了结构类型后,就可以定义新类型变量,来使用结构
route myRoute;
还可以通过句点字符访问这个组合变量中的数据成员
myRoute.direction = orientation.north;
myRoute.distance = 2.5;
*/
namespace mystruct
{
enum orientation : byte
{
north = 1,
south = 2,
east = 3,
west = 4
}
struct route
{
public orientation direction;
public double distance;
}
class Program
{
static void Main(string[] args)
{
route myRoute;
int myDirection = -1;
double myDistance;
Console.WriteLine("1) North\n2) South\n3)East\n4) West");
do
{
Console.WriteLine("Selecr a direction:");
myDirection = Convert.ToInt32(Console.ReadLine());
}
while ((myDirection < 1) || (myDirection > 4));
Console.WriteLine("Input a distance:");
myDistance = Convert.ToDouble(Console.ReadLine());
myRoute.direction = (orientation)myDirection;
myRoute.distance = myDistance;
Console.WriteLine("myRoute specifies a direction of {0} and a" + "distance of {1}", myRoute.direction, myRoute.distance);
Console.ReadKey();
}
}
}
/*
结构和枚举一样也是在代码的主体之外声明的,在名称空间声明中声明route结构及其使用的orientation枚举
enum orientation : byte
{
north = 1,
south = 2,
east = 3,
west = 4
}
struct route
{
public orientation direction;
public double distance;
}
代码的主题结构和前面的例子类似,要求输入一些信息并显示他们,把方向选项放在do循环中,对于用户的输入进行有效性检测
拒绝不属于1-4范围的整数输入,注意在引用route成员时,处理他们的方式与成员类型相同的变量完全一样
myRoute.direction = (orientation)myDirection;
myRoute.distance = myDistance;
可以直接把输入的值放到myRoute.distance中
myRoute.distance = Convert.ToDouble(Console.ReadLine());
还应进行有效性验证,但这段代码不存在这一步骤,对结构成员的任何访问都以相同的方式处理
数组
前面的类型有一个共同特点,它们值存储一个值,有时需要存储许多数据,这样就带来不方便
有时需要同时存储几个类型相同的值而不是每个值使用不同的变量
鉴定要对所有朋友的名字进行一些操作
string firendName1 = "Robert Barwell";
string firendName2 = "Mike Parry";
string firendName3 = "Jeremy Beacock";
但这看起来需要很多工作,特别是需要编写不同的代码来处理每个变量,例如不能在循环中
迭代这个字符串列表
另一种方式使用数组,数组是一个变量的索引列表,存储在数据类型的变量中,例如一个数组friendName
存储上述3个名字,在方括号中指定索引即可访问各个成员
firendName[<index>]
这个索引是一个整数第一个索引是0,第二个索引是1以此类推,这样就可以使用个循环遍历所有元素
int i;
for (i = 0; i < 3; i++)
{
Console.WriteLine("Name with index of {0}:{1}",i,firendName[i]);
}
声明数组
<basetype>[] <name>;
其中<basetype>可以是任何变量类型,数组必须在访问之前初始化
int[] myintarray;
myintarray[10] = 5;
上面两行不能访问错误
数组的初始化有两种方式,可以以字面形式指定数组的完整内容,也可以指定数组大小,在使用
关键字new初始化所有数组元素
使用字面值指定数组,只需要提供一个用逗号分隔的元素值列表,该列表放在花括号中,
int[] myintarray = {1,3,5,2,99};
其中myintarray有5个元素,每个元素都赋予了一个整数值
另一种方式
int[] myintarray = new int[5];
这里使用关键new显示的初始化数组,用一个常量值定义其大小,这种方式会给所有的数组元素
赋予同一个默认值,对于数值类型来说,其默认值是0
还可以两种结合一起
int[] myintarray = new int[5] {1,3,5,2,99};
这种方式数组大小必须与元素个数相匹配,不能向下面这种
int[] myintarray = new int[10] {1,3,5,2,99};
*/
namespace myarray
{
class Program
{
static void Main(string[] args)
{
string[] firendName = { "Robert Barwell", "Mike Parry", "Jeremy Beacock" };
int i;
Console.WriteLine("Here are {0} of my firends;", firendName.Length);
for (i = 1; i < firendName.Length; i++)
{
Console.WriteLine(firendName[i]);
}
Console.ReadKey();
}
}
}
/*
foreach
foreach循环可以使用一种简便的语法来定位数组中的每个元素
foreach (<baseType> <name> in <array>)
{
//can use <name> for each element
}
这个循环会迭代每个元素,依次把每个元素放在变量<name>中且不存在访问非法元素的危险
不需要考虑数组中有多少个元素,使用这个循环可
*/
namespace myarray1
{
class Program
{
static void Main(string[] args)
{
string[] firendNames = { "Robert Barwell", "Mike Parry", "Jeremy Beacock" };
int i;
Console.WriteLine("Here are {0} of my firends;", firendNames.Length);
foreach (string friendName in firendNames )
{
Console.WriteLine(friendName);
}
Console.ReadKey();
}
}
}
/*
这段代码输出结构和前面的完全相同使用这种方法和标准的for循序主要的区别在于foreach循环
对数组内容进行只读访问,所以不能任何元素值例如不能编写如下代码
foreach (string friendName in firendNames )
{
friendName = "rupert the bear";
}
使用for循环就可以给数组元素赋值
多维数组
声明
二维数组
<baseType>[,] <name>;
多维数组只需要更多的逗号
<baseType>[,,,] <name>;
该语句声明一个4维数组,赋值也使用类似语法,用逗号分隔大小,
例如要声明和初始化二维数组a基本类型double,x=3,y=4
double[,] a = new double[3,4];
还可以使用字面值进行初始的赋值
double[,] a = {{1,2,3,4},{2,3,4,5},{3,4,5,6}};
这个数组的维度与前面的相同也是3行4列,通过提供字面值隐式定义这些维度
要访问多维数组中的每个元素需要指定它们的索引
例如
a[2,1]值为4
数组的数组
a = new int[2][];
a[0] = new int[3];
a[1] = new int[4];
也可以使用上述字面赋值的一种改进形式
a = new int[3][] {new int[] {1,2,3}, new int[] {1},new int[] {1,2}};
还可以简化成把数组的初始化和声明放在同一行
int[][] a = { new int[] {1,2,3}, new int[] {1}, new int[] {1,2}};
对于锯齿数组可以使用foreach循环,但是通常需要使用嵌套
下面代码会失败
foreach (int divisor in divisors1to10)
{
Console.WriteLine(divisor);
}
因为数组divisors1to10包含int[]元素而不是int元素必须循环每个子数组和数组本身
foreach (int[] divisorOfInt in divisors1to10)
{
foreach (int divisor in divisorOfInt)
{
Console.WriteLine(divisor);
}
}
可以看出使用锯齿数组的语法复杂的多,需要根据实际情况来定义和使用
字符串的处理
目前对字符串的使用仅限于把字符串写到控制台上,从控制台上读取字符串,以及使用+运算符连接字符串
首先要注意,string类型变量可以看作char变量的只读数组
string mystring = "a string";
char mychar = mystring[1];
但是不能使用方式为各个字符赋值,为了获得一个可写的char数组,
string mystring = "a string";
char[] mychar = mystring.ToCharArray();
接着就可以采用标准方式处理char数组了也可以在foreach使用字符串
foreach (char character in mystring)
{
Console.WriteLine("{0}",character);
}
与数组一样还可以使用mystring.Length获取元素的个数
string mystring = Console.ReadLine();
Console.WriteLine("You typed (0) characters",mystring.Length);
其他的基本字符串处理技巧采用这种方式
例如<string>.ToLower(),<string>.ToUpper()
还有输入的时候无意在前面或后面添加了额外的空格
<string>.Trim()来处理
<string>.TrimStart()来处理首部的空格
<string>.TrimEnd()来处理结尾的空格
<string>.PadLeft(N)在左边添加N个空格
<string>.PadLeft(N,'-')在左边添加N个'-'
<string>.PadRight(N)在右边添加N个空格
*/