C#学习总结(一)

(一)基本概念

.NET框架,CLR和C#之间的关系。

.NET是一个独立发布的软件包,包括CLR,类库 和相关语言编译器

C#代码 经编译后 在CLR环境运行 


不同.NET版本的比较:

.NET3/3.5只是扩展了WF、WPF、WCF、WCS组件,没有更新C#编译器,CLR版本是2.0。


C、C++程序员在上世纪90年代,使用win32 API ,多数使用MFC(微软基础类库),一些人转向COM(组件对象模型)。

但是都有一些缺点:Win32 API不是面向对象的,使用比MFC复杂。

MFC虽然是面向对象的,但不一致

COM概念简单,但代码复杂

当时,windows开发主要针对桌面应用。


2002年微软发布.NET框架,比MFC和COM更一致,更面向对象。

.NET的特点:

多平台:可用于开发 服务器程序,桌面程序,PDA,移动电话程序。

行业标准:支持多种通信协议,XML,HTTP,SOAP,WSDL

安全: 相对安全了些


C#/VB代码==(编译)==>CIL (中间语言)===>机器语言==>CLR执行环境


.NET框架有自动回收垃圾功能,像java。C#的程序可以调用VB的类,前提要遵循一定的规则。.NET框架下的代码页可以调用Win32 DLL导出的纯C函数的代码,如Windows API(非NET)。不需要用COM组件!不需要使用注册表。有并行执行的特性。

(二)C#程序结构


filename.cs
using  System;
namespace NewSpace
{
   class Program 
   {
        static void Main()  //Main首字母大写!
        {
           Console.Write("Hello World!");
           Console.WriteLine("two numbers are  {0} and   {1}",1,2 );//采用替代位格式化输出
       }
    }
}
C#各种量的命名规则,是Pascal风格,多个单词首字母都大写。

C#注释:/* 多行注释 */    //单行注释              ///文档注释

(三)采用命令行方式,编译和运行C#

从VS2010的安装文件夹找到Visual Studo命令行。【直接cmd进入命令行不识别csc等命令】 csc  /?获得更多帮助

要首先切换到项目文件所在路径


生成可执行文件!


(四)C#中类型

C#中预定义的类型有:
简单类型: bool ,char      sbyte, byte  short ushort  int uint  long  ulong     decimal  float double  
复杂数据类型: object   string

用户可自行创建的类型有:
class 类类型
struct 结构类型
array 数组类型
enum 枚举类型
delegate 委托类型
interface 接口类型
栈:是一块内存数组,只能在栈顶读和写
堆:是内存区域,可以 任意顺序读和写,堆中虽然可以保持数据,但不能显示删除,靠GC垃圾回收期,清除无主的堆对象!

C#中访问修饰符有:
private:类内函数可以访问类内任何成员
public:只能从类的实例化对象访问类内属性或函数
protected
internal
protected internal
C#中四种参数类型:【重点】

参数类型

修饰符

是否在

声明时使用

是否在

调用时使用

执行

没有

   

系统把实参的值复制到形参。在函数返回后,形参一同从栈中弹出

引用

ref

形参是实参的别名

输出

out

形参是实参的别名

数组

params

允许传递可变目录的实参列表,编译器需要在堆中重新构建数组;也可以传递一个数组,不需要重建数组



C#中有9种类成员

数据成员

函数成员(执行代码)

字段

常量

方法

属性

构造函数

Finalizer方法

运算符

索引

事件

类成员修饰符顺序:

[  特性  ] [  修饰符  ]   核心声明  

           

修饰符有:pulic private static const(针对字段声明)

核心声明如: int x,  void  fun(int x)

类成员又可分为:

实例类成员:每个实例拥有各个类成员的copy

静态类成员:可被类的所有实例共享,即使没有实例也存在可以访问


其中可以声明为静态的类成员有:字段、方法、属性、构造函数、运算符、事件

注意:其他,常量、Finalizer方法、索引不可声明为静态


C#中没有全局变量,每个变量必须声明在类型中!
常量在内存中没有存储位置(不像静态变量有存储),尽在编译时被替换。

(五)相关代码

有关调用参数

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CSharp_Call
{

    class MyClass1
    {

        public int add(int x, int y)
        {
            return x + y;
        }

        //static属性的方法只能被本类的对象调用
        static int minus(int x, int y)
        {

            return x - y;
        }
        public void fun1(ref MyClass2 a, ref int b)
        {
            a.val = 24;
            b = 29;
        }

        public void fun2(out MyClass2 a, out int b)
        {
            //输出类型 参数,必须在函数调用之前初始化(与ref引用类型参数不同的地方),否则报错
            a = new MyClass2();
            a.val = 99;
            b = 100;
        }

        //数组参数作为形参:定义用用关键字params,调用时不用关键字。在一个参数列表最多只有一个数组参数,且放在其他参数的后面,数值类型后面要有[]
        public void displaylist(params int[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                Console.WriteLine("{0} ", arr[i]);
            }

            //也可以采用如下方式循环输出
            /*
            foreach (int elem in arr)
            {
                Console.WriteLine("{0} ", elem);
            }
             * */
        }

    }

    class MyClass2
    {

        public int val = 20;
    }

    class MyClass3
    {


    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass1 myobject = new MyClass1();
            int x = 3, y = 4;
            //值 参数的传递,复制一份实参到形参
            Console.WriteLine("{0}+{1}={2}", x, y, myobject.add(x, y)); //在Program类中调用MyClass类的函数时,必须声明MyClass的对象来调用
            MyClass2 myobj2 = new MyClass2();
            //直接调用另一个的属性,由于是复杂数据类型,栈中存放只是对象在堆中的引用
            Console.WriteLine("{0}", myobj2.val);

            //引用类型参数,函数定义和调用时都加上关键字ref,形参是实参的别名,指向相同内存单元
            myobject.fun1(ref myobj2, ref x);
            Console.WriteLine("{0},{1}", myobj2.val, x);

            //输出类型参数,函数定义和调用时都加上关键字out,形参是实参的别名,指向相同内存单元
            myobject.fun2(out myobj2, out x);
            Console.WriteLine("{0},{1}", myobj2.val, x);
            
            //注意数组的定义
            int[] myarr = new int[] { 1, 1, 2, 3, 5, 8, 11 };
            //直接传递一个数组参数,不需要编译器在堆中重新构造数组,直接存放在栈中
            myobject.displaylist(myarr);
            //传递一个实参列表,需要编译器在堆中重新构造数组
            myobject.displaylist(2, 4, 6, 8, 10);
            myobject.displaylist(1, 3, 5, 7);
        }
    }
}


有关类成员的

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassMember
{
    class MyClass1
    {

        int elem1;          //实例类成员——实例字段
        static int elem2=24;   //静态类成员 - -静态字段

       
        public void SetVars(int x, int y)
        {

            elem1 = x;
            elem2 = y; //像访问实例字段一样访问静态字段
        }
        public void Display(string str)
        {

            Console.WriteLine("{0}: elem1= {1},elem2={2}", str, elem1, elem2); //像访问实例字段一样访问静态字段
        }
    }

    class MyClass2
    {

        static public int A;        //静态字段
        static public void PrintA() //静态方法
        {

            Console.WriteLine("A: {0}", A);
        }
    }

    class MyClass3
    {

        const int val1 = 100;  //不能再其他类调用!
        //注意 常量成员的声明和定义必须在一起,不能分开写出 const int val1; val1=100;
        public const int val2 = 200;//用public修饰const,可被其他空间的类调用   不能用static修饰
    }

    class MyClass4
    {

        public int val0;
        //区别字段和属性,不能重名
        private int val;   //字段,分配内存
        
        public int myval   //属性:不分配内存,至少有一个set或get访问器,不允许有其他方法
        {
            set //set访问器
            {
                val = myval;
            }
            get //get访问器
            {
                return val;
            }
        }

        public int max
        {
            set
            {
               //方法也可以不与属性相对应,属性也可以与数据库关联
            }
            get            {

                return 10;
            }
        }

        public int readonlyPerporty //只有get方法的属性称为 只读属性,安全
        {
            get
            {
                return val;
            }
        }
        public int writeonlyPerporty //只有set方法的属性 称为 只写属性
        {
            set
            {
                val = 4;
                //在只有set方法是,不能用val=writeonlyPerporty赋值
            }
        }
    }

    class MyClass5
    {
        //自动实现属性,只声明属性而不声明后备字段,不提供访问器的方法体;除非通过访问器,否则不能访问后备字段
        public int myval
        {
            set;
            get;
        }

        static int val;
        public static int myval2 //静态属性,可在类内访问,也可从类外不用实例化访问
        {
            set { myval2 = val; }
            get { return val; }
        }
        public void PrintVal()
        {

            Console.WriteLine("val={0}", myval2);
        }

    }

    class MyClass6
    {
        public string LastName;
        public string FisrtName;
        public string BirthPlace;

        public string this[int index]  //索引没有名称,名称位置使用关键字this,索引参数列表在方括号中间,至少有一个参数
        {//和属性一样,索引不分配内存,不同的是索引通常访问多个数据成员
            set
            {
                switch (index) //set被调用时,接受2个数据:隐式参数value(要保存的数据)+索引参数
                {
                    case 0: LastName = value; break;
                    case 1: FisrtName = value; break;
                    case 2: BirthPlace = value; break;
                    default:
                        throw new ArgumentOutOfRangeException("index");
                        break;
                }
            }
            get
            {
                switch (index)
                {
                    case 0: return LastName;
                    case 1: return FisrtName;
                    case 2: return BirthPlace;
                    default: throw new ArgumentOutOfRangeException("index");
                        break;
                }
            }

        }
    }

    partial class MyClass7 //使用关键字 partial 一个类类型可以在两部分中,可以放在多个文件中。
    {

        public void Out1(int val){
            Console.WriteLine("out1:{0}",val);
        }
    }

    partial class MyClass7
    {
        public void Out2(int val)
        {
            Console.WriteLine("out2:{0}",val);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

           // Console.WriteLine("静态字段mem2={0}", new MyClass1().elem2);
            MyClass1 obj1 = new MyClass1();
      
            MyClass1 obj2 = new MyClass1();
          //  MyClass1.elem2 = 2012;
            // Console.WriteLine("静态字段mem2={0}",MyClass1.elem2);

            obj1.SetVars(2, 4);
            obj1.Display("obj1 ");//输出2,4

            obj2.SetVars(20, 40);
            obj2.Display("obj2");//输出20,40

            obj1.Display("obj1");//输出2,40
            //由于2个实例obj1,obj2公用1个静态字段elem,任何一个实例对elem2的改变都会影响到实例的对elem2的访问


            MyClass2.A = 10;   //使用.运算,不用实例化对象,直接访问静态字段
            MyClass2.PrintA();  //使用.运算,不用实例化对象,直接调用静态方法

            Console.WriteLine("常量 val2 :{0}", MyClass3.val2);//常量 像 静态字段一样,对每个实例都可见,不用实例化就可以访问
            //常量与 静态量不同的时,常量没有自己的存储位置,编译时被编译器替换,类似#define (常量不可用static修饰)

            MyClass4 obj4 = new MyClass4(); //仅从使用上不能区分属性和字段
            obj4.val0 = 5;     //给public的字段赋值
            obj4.myval = 10;   //给属性赋值,set访问器被隐式调用
            //obj4.myval.set(3);//注意:不能显示调用set访问器,否则报错
            Console.WriteLine("{0},{1}", obj4.val0, obj4.myval);//读取字段和属性,get访问器被隐式调用

            MyClass5 obj5 = new MyClass5();
            obj5.myval = 2012;
            Console.WriteLine("自动属性: {0}", obj5.myval);

            Console.WriteLine("静态属性:{0}", MyClass5.myval2);

            MyClass6 obj6 = new MyClass6();
            obj6[0]="Merry";
            obj6[1]="Shibe";
            obj6[2] = "Beijing";  //隐式调用索引的set访问器
            Console.WriteLine("Name: {0} {1}", obj6[1],obj6[0]); //调用索引的get访问器

            //注意:属性和索引都有get/set访问器,默认访问器的访问级别同成员本身。可以也可以单独设置访问器的访问级别,但要保证访问器的安全级别更高
            //public< protected( internal) < (protected/ internal) < private

            MyClass7 obj7 = new MyClass7();
            obj7.Out1(5);
            obj7.Out2(55);
        }
    }
}





  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值