C# 基础概念【一】

C# 基础概念【整理了 25 个问题】【一】
 
1.静态变量和非静态变量的区别?
2.const 和 static readonly 区别?
3.extern 是什么意思?
4.abstract 是什么意思?
5.internal 修饰符起什么作用?
6.sealed 修饰符是干什么的?
7.override 和 overload 的区别?
8.什么是索引指示器?
9.new 修饰符是起什么作用?

1. 静态变量和非静态变量的区别?
答:
静态变量:静态变量使用  static  修饰符进行声明 , 在所属类被装载时创建通过类进行访问所属类的所有实例的同一静态变量都是同一个值
非静态变量:不带有  static  修饰符声明的变量称做非静态变量 , 在类被实例化时创建通过对象进行访问同一个类的不同实例的同一非静态变量可以是不同的值
示例:
using System;
using System.Collections.Generic;
using System.Text; 
 
namespace Example01
{
    class Program
    {
        class Class1
        {
            public static String staticStr = "Class";
            public String notstaticStr = "Obj";
        }
        static void Main(string[] args)
        {
            //
静态变量通过类进行访问,该类所有实例的同一静态变量都是同一个值
            Console.WriteLine("Class1's staticStr: {0}", Class1.staticStr);
 
            Class1 tmpObj1 = new Class1();
            tmpObj1.notstaticStr = "tmpObj1";
            Class1 tmpObj2 = new Class1();
            tmpObj2.notstaticStr = "tmpObj2";
 
            //
非静态变量通过对象进行访问,不同对象的同一非静态变量可以有不同的值
            Console.WriteLine("tmpObj1's notstaticStr: {0}", tmpObj1.notstaticStr);
            Console.WriteLine("tmpObj2's notstaticStr: {0}", tmpObj2.notstaticStr);  
            Console.ReadLine();
        }
    }
}
结果:
Class1's staticStr: Class
tmpObj1's notstaticStr: tmpObj1
tmpObj2's notstaticStr: tmpObj2  
 
2.const   static readonly  区别?
答: const:  const  修饰符声明的成员叫常量,是在编译期初始化并嵌入到客户端程序
static readonly :
 static readonly  修饰符声明的成员依然是变量,只不过具有和常量类似的使用方法:通过类进行访问、初始化后不可以修改。但与常量不同的是这种变量是在运行期初始化

测试类:
using System;
using System.Collections.Generic;
using System.Text;
 
namespace Example02Lib
{
    public class Class1
    {
        public const String strConst = "Const";
        public static readonly String strStaticReadonly = "StaticReadonly";
        //public const String strConst = "Const Changed";
        //public static readonly String strStaticReadonly = "StaticReadonly Changed";
    }
}  
客户端代码:
using System;
using System.Collections.Generic;
using System.Text;
using Example02Lib;
 
namespace Example02
{
    class Program
    {
        static void Main(string[] args)
        {
            //
修改 Example02 Class1 strConst 初始值后,只编译 Example02Lib 项目
            //
然后到资源管理器里把新编译的 Example02Lib.dll 拷贝 Example02.exe 所在的目录,执行 Example02.exe
            //
切不可在 IDE 里直接调试运行因为这会重新编译整个解决方案!!
 
            //
可以看到 strConst 的输出没有改变,而 strStaticReadonly 的输出已经改变
            //
表明 Const 变量是在编译期初始化并嵌入到客户端程序,而 StaticReadonly 是在运行时初始化的
            Console.WriteLine("strConst : {0}", Class1.strConst);
            Console.WriteLine("strStaticReadonly : {0}", Class1.strStaticReadonly);
 
            Console.ReadLine();
        }
    }
}
结果:
strConst : Const
strStaticReadonly : StaticReadonly 

修改后的示例:
测试类:
using System;
using System.Collections.Generic;
using System.Text;
 
namespace Example02Lib
{
    public class Class1
    {
        //public const String strConst = "Const";
        //public static readonly String strStaticReadonly = "StaticReadonly";
        public const String strConst = "Const Changed";
        public static readonly String strStaticReadonly = "StaticReadonly Changed";
    }
}
结果
strConst : Const
strStaticReadonly : StaticReadonly Changed


3.extern  是什么意思?
答: extern  修饰符用于声明由程序集外部实现的成员函数 . 经常用于系统 API 函数的调用(通过  DllImport  )。注意,和 DllImport 一起使用时要加上  static  修饰符 ,
也可以用于对于同一程序集不同版本组件的调用(用  extern  声明别名) , 不能与  abstract  修饰符同时使用

示例:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
 
namespace Example03
{
    class Program
    {
        //
注意 DllImport 是一个 Attribute Property ,在 System.Runtime.InteropServices 命名空间中定义
        //extern
DllImport 一起使用时必须再加上一个 static 修饰符
        [DllImport("User32.dll")]
        public static extern int MessageBox(int Handle, string Message, string Caption, int Type);
 
        static int Main()
        {
            string myString;
            Console.Write("Enter your message: ");
            myString = Console.ReadLine();
            return MessageBox(0, myString, "My Message Box", 0);
        }
    }


4.abstract  是什么意思?
答: abstract  修饰符可以用于类、方法、属性、事件和索引指示器( indexer ),表示其为抽象成员 . abstract  不可以和  static  virtual  override  一起使用
声明为  abstract  成员可以不包括实现代码,但只有类中还有未实现的抽象成员,该类就不可以被实例化,通常用于强制继承类必须实现某一成员

示例:
using System;
using System.Collections.Generic;
using System.Text;
 
namespace Example04
{
    #region 
基类,抽象类
    public abstract class BaseClass
    {
        //
抽象属性,同时具有 get set 访问器表示继承类必须将该属性实现为可读写
        public abstract String Attribute
        {
            get;
            set;
        }
 
        //
抽象方法,传入一个字符串参数无返回值
        public abstract void Function(String value);
 
        //
抽象事件,类型为系统预定义的代理 (delegate) EventHandler
        public abstract event EventHandler Event;
 
        //
抽象索引指示器,只具有 get 访问器表示继承类必须将该索引指示器实现为只读
        public abstract Char this[int Index]
        {
            get;
        }
    }
    #endregion
 
    #region 
继承类
    public class DeriveClass : BaseClass
    {
        private String attribute;
 
        public override String Attribute
        {
            get
            {
                return attribute;
            }
            set
            {
                attribute = value;
            }
        }
        public override void Function(String value)
        {
            attribute = value;
            if (Event != null)
            {
                Event(this, new EventArgs());
            }
        }
        public override event EventHandler Event;
        public override Char this[int Index]
        {
            get
            {
                return attribute[Index];
            }
        }
    }
    #endregion
 
    class Program
    {
        static void OnFunction(object sender, EventArgs e)
        {
            for (int i = 0; i < ((DeriveClass)sender).Attribute.Length; i++)
            {
                Console.WriteLine(((DeriveClass)sender)[i]);
            }
        }
        static void Main(string[] args)
        {
            DeriveClass tmpObj = new DeriveClass();
 
            tmpObj.Attribute = "1234567";
            Console.WriteLine(tmpObj.Attribute);
 
            //
将静态函数 OnFunction tmpObj 对象的 Event 事件进行关联
            tmpObj.Event += new EventHandler(OnFunction);
 
            tmpObj.Function("7654321");
 
            Console.ReadLine();
        }
    }
}
结果:
1234567
7
6
5
4
3
2


5.internal  修饰符起什么作用?
答:
internal 
修饰符可以用于类型或成员,使用该修饰符声明的类型或成员只能在同一程集内访问 . 接口的成员不能使用  internal  修饰符

示例
Example05Lib 
项目的  Class1
using System;
using System.Collections.Generic;
using System.Text;
 
namespace Example05Lib
{
    public class Class1
    {
        internal String strInternal = null;
        public String strPublic;
    }
}
结果
Example05Lib 
项目的  Class2  类可以访问到  Class1   strInternal  成员
Example05 
项目的  Program  类无法访问到  Class1   strInternal  成员
 
 
6.sealed  修饰符是干什么的?
答:
sealed 
修饰符表示密封 . 用于类时,表示该类不能再被继承,不能和  abstract  同时使用,因为这两个修饰符在含义上互相排斥
用于方法和属性时,表示该方法或属性不能再被继承,必须和  override  关键字一起使用,因为使用  sealed  修饰符的方法或属性肯定是基类中相应的虚成员
通常用于实现第三方类库时不想被客户端继承,或用于没有必要再继承的类以防止滥用继承造成层次结构体系混乱
恰当的利用  sealed  修饰符也可以提高一定的运行效率,因为不用考虑继承类会重写该成员
示例:
using System;
using System.Collections.Generic;
using System.Text;  
namespace Example06
{
    class Program
    {
        class A
        {
            public virtual void F()
            {
                Console.WriteLine("A.F");
            }
            public virtual void G()
            {
                Console.WriteLine("A.G");
            }
        }
        class B : A
        {
            public sealed override void F()
            {
                Console.WriteLine("B.F");
            }
            public override void G()
            {
                Console.WriteLine("B.G");
            }
        }
        class C : B
        {
            public override void G()
            {
                Console.WriteLine("C.G");
            }
        }
        static void Main(string[] args)
        {
            new A().F();
            new A().G();
            new B().F();
            new B().G();
            new C().F();
            new C().G();  
            Console.ReadLine();
        }
    }
}
结果:
 B  在继承类  A  时可以重写两个虚函数,由于类  B  中对  F  方法进行了密封,   C  在继承类  B  时只能重写一个函数  
控制台输出结果,类  C  的方法  F  只能是输出  中对该方法的实现:
A.F
A.G
B.F
B.G
B.F
C.G 

7.override   overload  的区别?
答: override  表示重写,用于继承类对基类中虚成员的实现
overload 
表示重载,用于同一个类中同名方法不同参数(包括类型不同或个数不同)的实现
示例:
using System;
using System.Collections.Generic;
using System.Text;
 
namespace Example07
{
    class Program
    {
        class BaseClass
        {
            public virtual void F()
            {
                Console.WriteLine("BaseClass.F");
            }
        }
        class DeriveClass : BaseClass
        {
            public override void F()
            {
                base.F();
                Console.WriteLine("DeriveClass.F");
            }
            public void Add(int Left, int Right)
            {
                Console.WriteLine("Add for Int: {0}", Left + Right);
            }
            public void Add(double Left, double Right)
            {
                Console.WriteLine("Add for int: {0}", Left + Right);
            }
        }
        static void Main(string[] args)
        {
            DeriveClass tmpObj = new DeriveClass();
            tmpObj.F();
            tmpObj.Add(1, 2);
            tmpObj.Add(1.1, 2.2);
 
            Console.ReadLine();
        }
    }
}
结果:
BaseClass.F
DeriveClass.F
Add for Int: 3
Add for int: 3.3 

8. 什么是索引指示器?
答: 实现索引指示器( indexer )的类可以象数组那样使用其实例后的对象,但与数组不同的是索引指示器的参数类型不仅限于 int . 简单来说,其本质就是一个含参数属性
示例:  
using System;
using System.Collections.Generic;
using System.Text;
 
namespace Example08
{
    public class Point
    {
        private double x, y;
        public Point(double X, double Y)
        {
            x = X;
            y = Y;
        }
        //
重写 ToString 方法方便输出
        public override string ToString()
        {
            return String.Format("X: {0} , Y: {1}", x, y);
        }
    }
    public class Points
    {
        Point[] points;
        public Points(Point[] Points)
        {
            points = Points;
        }
        public int PointNumber
        {
            get 
            { 
                return points.Length; 
            }
        }    
        //
实现索引访问器
        public Point this[int Index]
        {
            get
            {
                return points[Index];
            }
        }
    }
 
    //
索引指示器的实质是含参属性,参数并不只限于 int
    class WeatherOfWeek
    {
        public string this[int Index]
        {
            get
            {
                //
注意 case 段使用 return 直接返回所以不需要 break
                switch (Index)
                {
                    case 0:
                        {
                            return "Today is cloudy!";
                        }
                    case 5:
                        {
                            return "Today is thundershower!";
                        }
                    default:
                        {
                            return "Today is fine!";
                        }
                }
            }
        }
        public string this[string Day]
        {
            get
            {
                string TodayWeather = null;
                //switch
的标准写法
                switch (Day)
                {
                    case "Sunday":
                        {
                            TodayWeather = "Today is cloudy!";
                            break;
                        }
                    case "Friday":
                        {
                            TodayWeather = "Today is thundershower!";
                            break;
                        }
                    default:
                        {
                            TodayWeather = "Today is fine!";
                            break;
                        }
                }
                return TodayWeather;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Point[] tmpPoints = new Point[10];
            for (int i = 0; i < tmpPoints.Length; i++)
            {
                tmpPoints[i] = new Point(i, Math.Sin(i));
            }
 
            Points tmpObj = new Points(tmpPoints);
            for (int i = 0; i < tmpObj.PointNumber; i++)
            {
                Console.WriteLine(tmpObj[i]);
            }
 
 
            string[] Week = new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Staurday"};
            WeatherOfWeek tmpWeatherOfWeek = new WeatherOfWeek();
            for (int i = 0; i < 6; i++)
            {
                Console.WriteLine(tmpWeatherOfWeek[i]);
            }
            foreach (string tmpDay in Week)
            {
                Console.WriteLine(tmpWeatherOfWeek[tmpDay]);
            }
 
            Console.ReadLine();
        }
    }
}
结果:
X: 0 , Y: 0
X: 1 , Y: 0.841470984807897
X: 2 , Y: 0.909297426825682
X: 3 , Y: 0.141120008059867
X: 4 , Y: -0.756802495307928
X: 5 , Y: -0.958924274663138
X: 6 , Y: -0.279415498198926
X: 7 , Y: 0.656986598718789
X: 8 , Y: 0.989358246623382
X: 9 , Y: 0.412118485241757
Today is cloudy!
Today is fine!
Today is fine!
Today is fine!
Today is fine!
Today is thundershower!
Today is cloudy!
Today is fine!
Today is fine!
Today is fine!
Today is fine!
Today is thundershower!
Today is fine!  

9.new  修饰符是起什么作用?
答: new  修饰符与  new  操作符是两个概念 .
new 
修饰符用于声明类或类的成员,表示隐藏了基类中同名的成员。而 new  操作符用于实例化一个类型 . new  修饰符只能用于继承类,一般用于弥补基类设计的不足
new 
修饰符和  override  修饰符不可同时用在一个成员上,因为这两个修饰符在含义上互相排斥 .
示例:
using System;
using System.Collections.Generic;
using System.Text;
 
namespace Example09
{
    class BaseClass
    {
        //
基类设计者声明了一个 PI 的公共变量,方便进行运算
        public static double PI = 3.1415;
    }
    class DervieClass : BaseClass
    {
        //
继承类发现该变量的值不能满足运算精度,于是可以通过 new 修饰符显示隐藏基类中的声明
        public new static double PI = 3.1415926;
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(BaseClass.PI);
            Console.WriteLine(DervieClass.PI);
 
            Console.ReadLine();
        }
    }
}
结果:
3.1415
3.1415926  

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值