分享

必知必会的40个C#语言方面的技术细节

 悟静 2012-11-18

细节01给C#代码加注释的意义
细节02装箱和拆箱
细节03理解值类型和引用类型

值类型变量不能为null,必须具有一个确定的值。引用类型被赋值前的值都是null
细节04隐式转换和显示转换
细节05前缀方式增1和减1运算符
细节06理解移位运算符
>>运算符将第一个操作数向右移动第二个操作数所指定的位数
<<运算符将第一个操作数向左移动第二个操作数所指定的位数
注意几点:
1.如果第一个操作数为int或uint,则移位数由第二个操作数的低五位给出
2.如果第一个操作数为long或ulong,则移位数由第二个操作数的低六位给出
例如:int i; i=48>>3 则i=6
48对应的二进制为00110000,右移3位后的二进制值为00000110,则十进制为6
细节07理解运算的次序
细节08理解参数的类型

输入参数,输出参数out,引用参数ref,参数数组params
细节09重载方法
细节10虚方法与重写方法

虚方法指允许被其子类重新定义的方法,在声明时需要用virtual修饰符
重写也称为覆盖override,是在派生类使用override修饰符重写基类中带有virtual修饰符的虚方法
注意:override修饰符不能与new,static,或virtual修饰符同时使用
,另外,重写方法只能用于重写基类中的虚方法,不能用来单独声明方法。
派生类中使用new关键字可以实现向基类成员隐藏继承成员。
public class Child:Parent
{
  public new string m()
{return "隐藏一般方法"}
}
细节11结构和类的区别
细节12什么是封装
细节13什么是继承
细节14什么是多态
细节15作用域的概念
细节16使用索引器

索引器就是能够让类像一个数组似的被访问。索引器与属性很相似,也有get和set访问器。
public string this[int Ind]
{
  get
{}
}
shapeName=s[Count];
细节17base和this关键字
base关键字用于派生类中访问基类的成员。使用范围如下:
1.调用基类中已被其他方法重写的方法
2.指定创建派生类实例时应调用的基类构造函数。
细节18理解静态修饰符
细节19。net的object类

System.Object类的核心成员如下:
Equals():确定两个object实例是否相等
Finalize():释放资源并执行其他清理操作。
GetHashCode():返回一个能够标识内存中指定对象的整数
GetType():获取当前实例的System.Type()对象
MemberwiseClone():返回当前对象逐个成员的副本
ToString()
细节20细说可空类型
在访问数据库数据时可能获得的数据为空值,这时可以考虑使用可空类型来定义字段或方法以更好的使用类来操作数据。
int?i=null;
int?等价于System.Nullable<int>
细节21分部类
public partial class Person
{}
开发分部类时,要成为同一类型的各个部分的所有分部类类型定义必须都在同一个程序集或者同一模快中。(。exe或dll)中进行定义,分部类定义不能跨越多个模块。
细节22匿名方法
匿名方法:在事件注册时直接将一个委托与一段代码相关联,这种代码就是匿名方法。
Sendbtn.Click+=delegate{"sda"};定义委托的后面要加上分号。
delegate void Msg(string str)//定义委托
public void GetMsg(string str)//定义与关联委托匹配的方法
{Response.Write("dads");}
Msg d =delegate(string str){Response.Write(str);}//委托与匿名方法的关联
Msg d= new Msg(GetMsg);//委托与命名方法关联
Sendbtn.Click+=delegate{Response.Write("safsaf");};//事件处理程序为匿名方法
细节23。net框架提供的属性(attribute)
。net框架提供了内置属性,这些属性都是从System.Attribute类派生而来的。
Conditional属性是System.Diagnostics.ConditionalAttribute的别名,该属性仅用于方法声明,即仅在C#编译器定义了作为属性参数出现的符号时,他才指定方法作为类的一部分
[Conditional(“参数”)]
启用调试状态时才作为类的一部分可以被调用,
Obsolete属性用于定义正被替换或者不再有效的代码。该属性有两个参数Message和IsError,Message用于设置错误信息字符串,IsError默认为false表示在编译代码时发出警告信息,True表示编译器将生成错误信息。
细节24自定义属性类(Attribute)
自定义属性类派生于System。Attribute类

自定义属性类的特定:

1.使用AttributeUsage属性可以限制属性的用法。

2.在AttributeUsage属性中可以指定是否可以多次使用属性。

3.可以设置属性参数。

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]//AttributeTargets.Class表示限制仅用于类。 AllowMultiple = true表示可以多次使用属性
    public class BookAttribute : Attribute
    {
        private string BookName;
        public BookAttribute(string bookname)//设置属性参数
        {
            this.BookName = bookname;
        }
        public string Book
        {
            get
            {
                return BookName;
            }
        }
    }
    //多次使用属性类
    [Book("细说ASP.NET;")]
    [Book("范例手册")]
    public class BookInfo
    {
        public string binfo = "图书信息-------";
        public BookInfo() { }
    }

     protected void Page_Load(object sender, EventArgs e)
        {
            BookInfo bf = new BookInfo();
            object[] Bookattr;
            System .Reflection .MemberInfo  Typeinfo=typeof (BookInfo );
            //提取类型是属性类的成员
            Bookattr = Typeinfo.GetCustomAttributes(typeof (BookAttribute ),false );
            if (Bookattr.GetLength(0) != 0)
            {
                BookAttribute ba = (BookAttribute)Bookattr[0];//获取属性类的第一个成员
                BookAttribute ba2=(BookAttribute )Bookattr [1];//获取属性类的第二个成员
            }

}
细节25泛型
细节26包含/委托
类似适配器模式,把类中定义对象,然后自定义方法,然后在方法体中用到定义的对象中的方法。
细节27实现迭代器
迭代器是可以返回相同类型值的有序序列的一段代码,可用做方法、运算符或get访问器的代码体。可以在类中实现多个迭代器,每个迭代器都必须像类成员一样有唯一的名称。并且可以再foreach语句中被客户端代码调用。迭代器的返回类型必须为IEnumerable或IEnumerator中任意一种,也可以是实现这两个接口的类。
IEnumerable接口:包含了。net框架用于从对象中提取元素的方法。如果类包含一个元素的集合,并希望其他代码段使用foreach循环语句遍历该集合中的每一个元素则应该在类上实现该接口。
IEnumerable接口值包含一个方法定义GetEnumerator(),用于返回一个循环访问集合的枚举数。
IEnumerator接口:支持对非泛型集合的简单迭代。该接口定义了一个属性和两个方法
1.Object Current{get}属性,获取集合中的当前元素
2.bool MoveNext()方法,访问集合的下一个元素
3.void Reset()方法,设置枚举数为其初始位置。
使用时必须引用System。Collection命名空间
public class Car : IEnumerable, IEnumerator
    {
        private short flag = -1;
        public IEnumerator GetEnumerator()
        {
            return  this;
        }
        public object Curretn
        {
            get
            {
                switch (flag)
                {
                    case 0:
                        return "aodi";
                    case 1:
                        return "huangguan";
                    default :
                        return "this is Error";
                }
            }
        }
        public bool MoveNext()
        {
            flag++;
            if(flag ==2)
            {
                return false;
            }
            return true;
        }
        public void ReSet()
        {
            flag = -1;
        }
    }
 static void Main(string[] args)
        {
            Car car = new Car();
            foreach (string s in car)
            {
                Response.Write(s+"</br>");
            }
        }
使用C#中的yield return命令也可以实现迭代器
细节28压缩和解压缩流的方法
在。net中,systtem.Io.Strem 类是所有流类型的虚基类。操作文件的FileStrem,操作内存的MemoryStrem操作网络的NetworkStrem
Stream类的Read()方法用于从当前流中读取字节序列。
public abstract int Read()
{
  byte[] buffer,//字节数组
  int offset,//表示从开始读取的位置
  int count//读取的最大字节数
}
Stream类的Write()方法用于从当前流中写入字节序列。并返回写入的字节数
public abstract int Write()
{
  byte[] buffer,//字节数组
  int offset,//表示从开始写入的位置
  int count//写入的字节数
}
一般情况下,对文件或数据可以进行压缩或解压缩操作。实质上就是对流的操作。在。net框架的System.IO.Compression命令空间下提供了GZipStream类,可以实现对流的压缩和解压缩。
public GZipStream
(
  Stream stream;//要压缩或解压缩的流
  CompressionMode mode;//要采取的操作(Compress压缩流或Decompress解压缩流)
  bool leaveOpen (true表示将流保留为打开状态,false表示流为关闭状态)
)
 //定义一个用于读取指定数据流中的数据的方法
        private const int bufferlength=1024;
        public static Byte[] ReadBytes(Stream stream, int bufferlength)
        {
           Byte[]buffer=new Byte  [bufferlength ];
           List<Byte> data = new List<Byte>();
           int real;
           while ((real = stream.Read(buffer, 0, bufferlength)) > 0)
           {
               if (real < bufferlength)
               {
                   Byte[] temp = new Byte[real];
                   Array.Copy(buffer, temp, real);
                   data.AddRange(temp);
               }
               else
               {
                   data.AddRange(buffer );
               }
           }
           return data.ToArray();
        }
         //定义一个向当前流中写入字节数组数据
        public static void WriteBytes(Stream stream, Byte[] data, int bufferlength)
        {
           Byte[]buffer=new Byte[bufferlength ];
           for (long g = 0; g < data.LongLength; g += bufferlength)
           {
               int le = bufferlength;
               if (g + bufferlength > data.LongLength)
               {
                   le=(int)(data.LongLength -g);
               }
               Array.Copy(data,g,buffer,0,le );
               stream.Write(buffer,0,le );
           }
        }
        //自定义方法压缩流,并调用前面定义的方法
        //压缩字节数据
        public Byte[] CompressByte(Byte[] data)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                //提供压缩内存流的方法
                using (System.IO.Compression.GZipStream gs = new System.IO.Compression.GZipStream(ms, CompressionMode.Compress, true))
                {
                    WriteBytes(gs,data,bufferlength );//将数据写入压缩流
                }
                return ms.ToArray();//返回压缩后的数据
            }
        }
        //自定义方法解压缩流
        public static Byte[] DeCompressByte(Byte[] data)
        {
            using (MemoryStream ms = new MemoryStream(data ))//数据存于内存流
            {
                //提供解压缩的方法
                using (System.IO.Compression.GZipStream gs = new System.IO.Compression.GZipStream(ms, CompressionMode.Decompress, true))
                {
                    return ReadBytes(gs, bufferlength);//读取解压缩流中的数据
                }
               
            }
        }
细节29C#中的深复制和浅复制
浅复制是指复制一个对象的时候,复制原始对象中所有的非静态值类型成员和所有的对应类型成员的引用
深复制是指不仅仅复制所有的非静态值类型成员,而且还复制所有引用类型成员的实际对象。
细节30全角字符转换为半角
全角字符是指一个字符占用两个标准字符位置。
半角字符是指一个字符占用一个标准字符的位置。
 //判断字符是否英文半角字符或标点
        public static bool IsHalflChar(char c)
        {
            int i = (int)c;
            return i >= 32 && i <= 126;

        }
        //判断字符是否全角或标点
        public static bool IsAllChar(char c)
        {
            if(c=='\u3000')return true ;
            int i =(int )c-65248;
            if (i < 32) return false;
            return IsHalflChar((char)i);

        }
        //将字符串中的全角字符转换和为半角
        public static string aToh(string s)
        {
            if(s==null ||s.Trim ()==string.Empty )return s;
            StringBuilder sb = new StringBuilder(s.Length );
            for (int i = 0; i < s.Length; i++)
            {
                if (s[i] == '\u3000') { sb.Append('\u0020'); }
                else if (IsAllChar(s[i])) { sb.Append((char)((int)s[i] - 65248)); }
                else
                    sb.Append(s[i]);
            }
            return sb.ToString();
        }
细节31分析路径字符串函数总结
相对路径:指相对对于网站地址的文件路径。
绝对路径:指磁盘上的一个指定位置。
C#中通过Path类的相关方法可以分析路径字符串。
GetDirectoryName:返回指定路径字符串的目录信息
GetExtension:返回指定的路径字符串的扩展名
GetFullPath:返回指定路径字符串的绝对路径
GetPathRoot:获取指定路径的根目录信息
HasExtension:确定路径是否包含文件扩展名
IsPathRooted:获取一个值,该值指示指定的路径字符串是包含绝对路径信息true还是包含相对路径信息false。
 //分析路径字符串
        protected void FenSi()
        {
            string str = string.Empty;
            string path1 = "c:\\temp\\blog.txt";
            string path2 = @"c:\\temp\\blog";
            string path3 = @"Record";
            if (Path.HasExtension(path1))
            {
                str = string.Format("路径{0});下有一扩展名为{1}的文件,属于目录{2}", path1, Path.GetExtension(path1), Path.GetDirectoryName(path1 ));
            }
            if (Path.IsPathRooted(path2))
            {
                string.Format("路径{0}的根目录为{1}",path2 ,Path .GetPathRoot (path2));
            }
            str = string.Format("路径{0}的全路径为{1}",path3,Path .GetFullPath (path3));
        }
细节32重载一元。二元运算符
细节33对象也能排序

System.Array类提供的Sort()静态方法可以根据数字、字母顺序对数组中的项进行排序。
System.ICompareTo()接口指定了一种允许一个对象可基于某些特定键值进行排序的方法。该接口提供一个CompareTo()方法用于比较当前实例与同一类型的另一个对象。
返回值小于0表示当前实例小于另一个对象。
 public class Student : IComparable
    {
        private int sid;
        public string name;
        public Student(int sid, string name)
        {
            this.sid = sid;
            this.name = name;
        }
        public int ID
        {
            get{return sid;}
            set { sid = value; }
        }
        int IComparable.CompareTo(object obj)
        {
            Student s = (Student)obj;
            if (this.sid > s.sid)
            {
                return 1;
            }
            if (this.sid < s.sid)
            {
                return -1;
            }
            else
                return 0;
        }
    }
string str = string.Empty;
            Student []arr=new Student [4];
            arr[0] = new Student(65,"张三");
            arr[1] = new Student(62, "张三");
            arr[2] = new Student(63, "张三");
            arr[3] = new Student(63, "张三");
            Array.Sort(arr);//对象排序
            foreach (var item in arr)
            {
 
            }
细节34实现IDisposable接口清除对象
利用。net框架提供的方法处理非内存资源,也就是通过实现IDisposable接口来释放非托管的资源。
IDisposable接口:它的Dispose()方法用于执行与释放或重置非托管资源相关应用程序定义的任务。
为using语句提供的对象必须实现IDisposable接口,此接口提供了Dispose()方法,该方法释放资源。
public class Test : IDisposable
    {
        public Test()
        { Console.WriteLine("a"); }
        ~Test()
        { Console.WriteLine("b"); }
        public void Dispose()
        {
            Console.WriteLine("c");
        }
    }
 static void Main(string[] args)
        {
            try
            {
                using (Test te = new Test())
                {
                    throw new Exception("safaf");
                }
            }
            catch { }
        }
运行结果:
a
c
b
细节35将字符串转成字符数组
。net框架在System.IO命名空间下的StringRead类可以实现把字符串转换为字符数组
StringRead类的Read()方法用于读取输入字符串中的字符快
public override int Read()
{
  char[] buffer,//读取到的字符数组
  int index,//表示从开始读取的位置
  int count//要读取的字符数
}
  //将字符串转换为字符数组
        protected void ZhuanHuan()
        {
            string str = "are you Read";
            char[]c=new char[200];
            StringReader sr = new StringReader(str);
            sr.Read(c,0,19);
        }
细节36将字符数组写入到字符串
StringBuider类和StringWriter类可以实现
public override int Read()
{
  char[] buffer,//读取到的字符数组
  int index,//表示从开始读取的位置
  int count//要读取的字符数
}
 //将字符数组写入字符串
        protected void Zhuan()
        {
            StringBuilder sb = new StringBuilder("One World");
            char[] c = { '.','0','n','e','c','d',};
            StringWriter sw = new StringWriter(sb);
            sw.Write(c,0,4);
        }
细节37使用var创建隐型局部变量
var关键字指示编译器能根据变量的初始化 表达式推断出变量的类型。
细节38Lambda表达式
构成:一个参数列表,Lambda操作符(=>),表达式()或语句块{}
Lambda表达式有两种。Lambda操作符右边是表达式的叫做表达式Lambda,如果是一个大括号括起来的任意多条语句,那就是语句Lambda
Lambda表达式赋值给委托类型必须满足一下条件:
1.Lambda表达式与委托类型的参数个数相同
2.Lambda表达式的每个参数都能被隐式的转化为委托类型的参数类型
3.Lambda表达式的返回值能够被隐式转化为委托类型的返回值类型。
 delegate int AddOne(int i);
        delegate int ToAdd(int i,int j);
        delegate void Method();
        delegate int Method1();
        protected void Lambda()
        {
            AddOne addone;
            addone = x => x + 1; //隐式类型,表达式方式体
            addone = x => { return x + 1; };//隐式类型,语句方法体
            addone = (int x) => x + 1;//显示类型,表达式方式体
            addone = (int x) => { return x + 1; };//显示语句方法体类型,
            ToAdd myto = (x, y) => x + y;//多个参数
            Method method1 = () => { };//无参数,表达式方式体
            Method1  method2 = () => 1;//无参数,语句方法体

        }
细节39生成缩略图的方法
Web应用中传输较大图片时除了采用压缩格式传输外,还可以使用缩略图的方式加快浏览速度。
生成图片缩略图主要应用了Image类的GetThumbnailImage()方法
该方法返回当前Image实例的缩略图
public Image GetThumbnaiImage(
  int thumbWidth,//请求的缩略图的宽度
  int thumbHeight,//请求的缩略图的高度
  Image.GetThuumbnailImageAbort callback,//创建一个委托并在该参数中传递对此委托的引用。
  IntPtr callbackData//必须为Zero
)
 //生成缩略图
        /// <summary>
        ///
        /// </summary>
        /// <param name="imgPath">原图片路径</param>
        /// <param name="thumbPath">缩略图存储路径</param>
        /// <param name="width">原图片的宽度</param>
        /// <param name="height">高度</param>
        private void Thumb(string imgPath, string thumbPath, double width, double height)
        {
            //生成缩略图
            System.Drawing.Image image = System.Drawing.Image.FromFile(imgPath  );
            System.Drawing.Image.GetThumbnailImageAbort callb = null;
            int w, h;
            //根据实际的宽度和高度确定缩略图的宽高
            if (width > height)
            {
                w = 100;
                h = Convert.ToInt32(Convert.ToSingle(height) / Convert.ToSingle(width)) * 80;

            }
            else
            {
                h = 100;
                w = Convert.ToInt32(Convert.ToSingle(width ) / Convert.ToSingle(height )) * 80;
            }
            System.Drawing.Image newimage = image.GetThumbnailImage(w,h,callb,new System .IntPtr ());
            //上传缩略图
            newimage.Save(thumbPath );
            newimage.Dispose();
            image.Dispose();

        }
细节40使用缓冲流
。net框架提供的在System.Io命令空间下的BufferedStream类可以实现缓冲数据,减少对操作系统的调用次数。
BufferedStream类提供从基础数据源或存储库读取字节以及将字节写入基础数据源或存储库的实现,在不需要缓冲区时可以防止缓冲区降低输入和输出速度。
BufferedStream类的Read()方法用于从当前缓冲流复制到字节数组
public overrider int Read()
{
  byte[] array,//复制到的字节数组
  int offset,//表示从开始读取的位置
  int count//要读取的字节数
}
BufferedStream类的Write()方法将字节复制到缓冲流
public override int Write()
{
  byte[] array,//从字节数组中复制数据
  int offset,//表示从开始写入的位置
  int count//写入的字节数
}
    //将一个文件的内容复制到另一个文件
        /// <summary>
        ///
        /// </summary>
        /// <param name="oPath">源文件路径</param>
        /// <param name="copyPath">目标文件路径</param>
        private void Buf(string oPath, string copyPath)
        {
            Stream s1, s2;
            BufferedStream bs1, bs2;
            byte[]b=new byte[1024];
            int i;
            //分别以读写方式打开文件
            s1 = File.OpenRead(oPath );
            s2 = File.OpenWrite(copyPath );
            //使用缓冲流
            bs1 = new BufferedStream(s1 );
            bs2 = new BufferedStream(s2);
            i = bs1.Read(b,0,1024);
            //从文件1中读取写入到文件2中
            while (i > 0)
            {
                bs2.Write(b,0,i);
                i = bs1.Read(b,0,1024);
            }
            bs2.Flush ();
            s1 .Close ();
            bs2 .Close ();

        }

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约