博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#基础笔记——语言基础
阅读量:4573 次
发布时间:2019-06-08

本文共 10448 字,大约阅读时间需要 34 分钟。

一、概述:

C#基础我想每一个.NET程序猿都学习过,但是如何使用才是最优方法呢?往往这些基础知识被大家忽略。

怎样操作字符串?如何进行类型转换?什么是克隆?为什么需要HashCode?

今天我们就来系统的回顾一下基础知识。

二、实现:

1. 字符串拼接

下面我们看一下下面代码:

string a = "t";string b = "e";string c = "s";//方法1string result = a + b + c;//方法2StringBuilder strBuilder = new StringBuilder();strBuilder.Append(a);strBuilder.Append(b);strBuilder.Append(c);string resultBuilder = strBuilder.ToString();//方法3,string.Format("{0}{1}{2}", a, b, c);

  方法1,对字符串进行进行“=”或者“+”操作时,内存都会创建一个新的字符串对象并且分配新的空间。

  方法2,StringBuilder不会重新创建一个string对象,而是以托管的方式分配内存

  方法3,推选,Format内部使用StringBuilder实现的,但是操作更灵活清晰。

2. 使用默认类型转换

下面我们介绍一下Parse和TryParse哪个更实用

string str = string.Empty;            string str1 = "123";            double d = 0D;            long ticks;            Stopwatch sw = Stopwatch.StartNew();            for (int i = 0; i < 1000; i++)            {                try                {                    d = Double.Parse(str1);                }                catch                {                    d = 0;                }            }            sw.Stop();            ticks = sw.ElapsedTicks;            Console.WriteLine("Parse()耗时:{0},执行结果:{1}", ticks, d);            //这样做是安全的,但是结构太繁琐,让我们试试              sw = Stopwatch.StartNew();            for (int i = 0; i < 1000; i++)            {                if (!Double.TryParse(str1, out d))                {                    d = 0;                }            }            sw.Stop();            ticks = sw.ElapsedTicks;            Console.WriteLine("TryParse耗时:{0},执行结果:{1}", ticks, d);

输出结果:

  Parse()耗时:32553653,执行结果:0

  TryParse()耗时:638,执行结果:0

3. 区别对待强制转型与as和is

我们有两个类,

class FirstType    {        public string Name { get; set; }    }  class SecondType : FirstType    { }

如何进行类型转换:

SecondType secondType = new SecondType() { Name = "Abel" };  FirstType firstType1 = (FirstType)secondType;  FirstType firstType2 = secondType as FirstType;

很明显As更可读。

4.使用int?确保值类型也可以为null

数据存储中数据库所有变量的初始值都可以为null,包括基类型int,我们在程序中如何实现呢?

int? num = null;            int cons = 0;            num = cons;            Console.WriteLine("int? num 被成功赋值:{0}", num);            //反过来          int? consnum = 1234;            int number;            if (consnum.HasValue)            {                number = consnum.Value;            }            else            {                number = 0;            }            //number = consnum ?? 0;            Console.WriteLine("number被成功赋值:{0}", number);

 

代码中备注掉的部分(number = consnum ?? 0)与上面的if实现功能一样,但更简洁。

与双目运算符(?:)差不多,consnum.HasValue为true则将consnum.Value值赋给number,否则number的值为0

5.区分readonly与const的使用方法

const是一个变异期的常量,readonly是运行期的常量

const至修饰基元类型,枚举,字符串类型,readonly没有限制。

const是编译型常量所以它天然就是static的,不能手动再为const添加static修饰。

readonly的全部意义在于运行第一次赋值后将不会改变。当然不可改变分两层意思:对于基类型变量本身不能改变,对于引用类型本身指针不可改变。

6.运算符重载:

我们实现对象相加重载

 

class OperatorSalary    {        public float RMB { get; set; }        public static OperatorSalary operator +(OperatorSalary s1, OperatorSalary s2)        {            s1.RMB += s2.RMB;            return s1;        }    }

 

调用代码:

OperatorSalary mikeincom = new OperatorSalary() { RMB = 22 };OperatorSalary roseincom = new OperatorSalary() { RMB = 33 };OperatorSalary allincom = mikeincom + roseincom;Console.WriteLine("工资和为: {0}", allincom.RMB);

这样我们实现对象相加重载,基本运算重载都是类似的。

7.对象比较器:

对象比较器重写需要继承接口IComparable<T>和IComparer<T>

 

class Salary : IComparable
{ public string Name { get; set; } public float BaseSalary { get; set; } public float Bonus { get; set; } public int CompareTo(Salary other) { return this.BaseSalary.CompareTo(other.BaseSalary); } } class BonusComparer : IComparer
{ public int Compare(Salary x, Salary y) { return x.Bonus.CompareTo(y.Bonus); } }

 

实现代码如下:

List
CompanySalary = new List
(){ new Salary{Name="Abel",BaseSalary=20000.10f,Bonus=1000f}, new Salary{Name="Tomson",BaseSalary=40000.10f,Bonus=2000f}, new Salary{Name="Lucy",BaseSalary=30000.10f,Bonus=4000f}, new Salary{Name="Erwin",BaseSalary=60000.10f,Bonus=5000f}, new Salary{Name="Steven",BaseSalary=80000.10f,Bonus=3000f} }; //首先我们以基本工资排序 CompanySalary.Sort(); foreach (Salary item in CompanySalary) { Console.WriteLine(string.Format("Name:{0} \t Basesalary:{1} \t Bonus:{2}",item.Name,item.BaseSalary,item.Bonus)); } //然后我们以奖金排序 CompanySalary.Sort(new BonusComparer()); foreach (Salary item in CompanySalary) { Console.WriteLine(string.Format("Name:{0} \t Basesalary:{1} \t Bonus:{2}", item.Name, item.BaseSalary, item.Bonus)); }

8.区别对待==和Equals

重写Equals时也需要重写GetHashCode这需要继承IEquatable<T>泛型接口

 

class PersonMoreInfo    {        public string SomeInfo { get; set; }    }    class Person:IEquatable
{ public string IDcode { get; private set; } public string Name { get; set; } public Person(string idcode) { this.IDcode = idcode; } public override bool Equals(object obj) { return this.IDcode==(obj as Person).IDcode; } public bool Equals(Person otherPerson) { return this.IDcode == otherPerson.IDcode; } public override int GetHashCode() { //return this.IDcode.GetHashCode();// 它永远返回一个整型类型,而整型显然无法满足字符串的容量,这是可能返回相同的Hashcode。 //下面写法避免HashCode重复: return (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "#" + this.IDcode).GetHashCode(); } }

 

实现代码:

Dictionary
PersonValue = new Dictionary
(); PersonMoreInfo abelValue = new PersonMoreInfo() { SomeInfo = "Mike's info" }; Person Abel = new Person("NB0903100006"); Person Erwin = new Person("NB0903100006"); PersonValue.Add(Abel, abelValue); Console.WriteLine("Abel的HashCode:",Abel.GetHashCode()); Console.WriteLine(string.Format("Abel和Erwin{0}", Abel.Equals(Erwin) ? "相等" : "不相等")); Console.WriteLine(string.Format("Abel和Erwin{0}", PersonValue.ContainsKey(Erwin) ? "相等" : "不相等"));

9.格式化字符串

重写ToString()方法需要继承IFormatttable接口

class People : IFormattable    {        public string IDCode { get; set; }        public Name Name { get; set; }        //实现接口IFormattable的ToString        public string ToString(string nameType, IFormatProvider formatProvider)        {            NameWord peopleNameToString = new NameWord();            var method=typeof(NameWord).GetMethod(nameType);            object obj=new object();            obj = this;            return method.Invoke(peopleNameToString, new object[] { obj }).ToString();        }      }    class Name    {        public string FirstName { get; set; }        public string LastName { get; set; }    }    class NameWord    {        public string chineseName(People people)        { return string.Format("中文名字:{0}", people.Name.FirstName); }        public string englishName(People people)        { return string.Format("英文名字:{0}.{1}", people.Name.FirstName,people.Name.LastName); }        public string japaneseName(People people)        { return string.Format("日语名字:{0}.{1}", people.Name.FirstName, people.Name.LastName); }        public string franceName(People people)        { return string.Format("法语名字:{0}.{1}", people.Name.FirstName, people.Name.LastName); }        public string elseName(People people)        { return this.ToString(); }    }

代码实现:

People abelzhang = new People() { IDCode = "123", Name = new Name() { FirstName="zhang",LastName="Abel"} };Console.WriteLine(abelzhang.ToString("chineseName", null));

这里本想用反射和表驱动法代替Switch,但是重写ToString方法发参数必须是string类型的,无法使用enum类型。

希望匠友们给出宝贵意见。

10.克隆:正确实现前拷贝和深拷贝

[Serializable]    class Employee : ICloneable    {        public string IDCode { get; set; }        public int Age { get; set; }        public Department department { get; set; }        public object Clone()        {            return this.MemberwiseClone();        } //用序列化实现深拷贝         public Employee DeepClone()        {             using(Stream objectStream=new MemoryStream() )            {                IFormatter formatter = new BinaryFormatter();                formatter.Serialize(objectStream, this);                objectStream.Seek(0, SeekOrigin.Begin);                return formatter.Deserialize(objectStream) as Employee;            }        } //实现浅拷贝         public Employee ShallowClone()        {            return Clone() as Employee;        }    }    [Serializable]    class Department    {        public string Name { get; set; } public override string ToString()        {            return this.Name.ToString();        }    }

这里深拷贝用序列化实现的。

Employee AbelCopy = new Employee() { IDCode = "123", Age = 26, department = new Department() { Name="Abel"} };    Employee LucyCopy = AbelCopy.ShallowClone();    Employee ErwinCopy = AbelCopy.DeepClone();    Console.WriteLine("LucyCopy---ID:{0},Age:{1},Department:{2}", LucyCopy.IDCode, LucyCopy.Age, LucyCopy.department.Name);    Console.WriteLine("ErwinCopy---ID:{0},Age:{1},Department:{2}", ErwinCopy.IDCode, ErwinCopy.Age, ErwinCopy.department.Name);    AbelCopy.IDCode = "321";    AbelCopy.Age = 27;    AbelCopy.department.Name = "Lucy";    Console.WriteLine("LucyCopy---ID:{0},Age:{1},Department:{2}", LucyCopy.IDCode, LucyCopy.Age, LucyCopy.department.Name);    C

11.简单的反射实现

我们先有一个普通的类。

public class DynamicSample    {        public string Name { get; set; }        public int Add(int a, int b)        {            return a + b;        }    }

实现Add方法的反射

int times = 1000000;    DynamicSample reSample = new DynamicSample();    var addMethod= typeof(DynamicSample).GetMethod("Add");    Stopwatch WatchDynamic1=Stopwatch.StartNew();    for (int i = 0; i < times; i++)    {        addMethod.Invoke(reSample,new object[]{
1,2}); } WatchDynamic1.Stop(); Console.WriteLine(string.Format("反射耗时:{0}毫秒", WatchDynamic1.ElapsedMilliseconds)); dynamic dySample = new DynamicSample(); Stopwatch WatchDynamic2 = Stopwatch.StartNew(); for (int j = 0; j < times; j++) { dySample.Add(1,2); } WatchDynamic2.Stop(); Console.WriteLine(string.Format("dynamic耗时:{0}毫秒", WatchDynamic2.ElapsedMilliseconds));

输出结果:

反射耗时:3490毫秒

dynamic耗时:330毫秒

从上面的例子分析dynamic实现反射的效率更高,但是这只适用于简单的反射,更复杂的反射还需要上面的方法处理。

 

 

 

        

转载于:https://www.cnblogs.com/Abel-Zhang/p/BaseOfLanguage.html

你可能感兴趣的文章
大数据等最核心的关键技术:32个算法
查看>>
Maven多模块项目搭建
查看>>
Scala
查看>>
Android 中LinearLayout控件属性
查看>>
面向对象之多态性
查看>>
树状数组
查看>>
【2019.8.14 慈溪模拟赛 T1】我不是!我没有!别瞎说啊!(notme)(BFS+DP)
查看>>
多任务--进程 及 进程间通信
查看>>
多线程/多进程+QProgressBar实现进度条
查看>>
多任务(进程)案例----- 拷贝文件夹
查看>>
Kotlin的快速入门
查看>>
底层原理
查看>>
21. Merge Two Sorted Lists
查看>>
创建数组
查看>>
dict使用
查看>>
ASP.NET MVC的帮助类HtmlHelper和UrlHelper
查看>>
02_ListActive中响应事件 并LogCat输出
查看>>
doubleclick adx note
查看>>
Celery框架
查看>>
[c#]asp.net开发微信公众平台(4)关注事件、用户记录、回复文本消息
查看>>