C# 基础概念【二】

10.this 关键字的含义?
11.
可以使用抽象函数重写基类中的虚函数吗?
12.
密封类可以有虚函数吗?
13.
如果基类中的虚属性只有一个属性访问器,那么继承类重写该属性后可以有几个属性访问器?如果基类中有 get  set 两个呢?
14.abstract 可以和 virtual 一起使用吗?可以和 override 一起使用吗?
15.
接口可以包含哪些成员?
16.类和结构的区别?
17.
接口的多继承会带来哪些问题?
18.
抽象类和接口的区别?

10. this 关键字的含义?
答: this 是一个保留字,仅限于构造函数和方法成员中使用.
在类的构造函数中出现表示对正在构造的对象本身的引用,在类的方法中出现表示对调用该方法的对象的引用,在结构的构造上函数中出现表示对正在构造的结构的引用,在结构的方法中出现表示对调用该方法的结果的引用.

this  保留字不能用于静态成员的实现里,因为这时对象或结构并未实例化 .  C#  系统中, this  实际上是一个常量,所以不能使用  this++  这样的运算 .
this 
保留字一般用于限定同名的隐藏成员、将对象本身做为参数、声明索引访问器、判断传入参数的对象是否为本身

示例:
using System;
using System.Collections.Generic;
using System.Text;
 
namespace Example10
{
    class Class1
    {
        private double c;
        private string value;
 
        public double C
        {
            get
            {
                return c;
            }
        }
        public Class1(double c)
        {
            //
限定同名的隐藏成员
            this.c = c;
        }
        public Class1(Class1 value)
        {
            //
用对象本身实例化自己没有意义
            if (this != value)
            {
                c = value.C;
            }
        }
        public override string ToString()
        {
            //
将对象本身做为参数
            return string.Format("{0} Celsius = {1} Fahrenheit", c, UnitTransClass.C2F(this));
        }
 
        //
由于好奇,在这做了一个效率测试,想看看到底哪种方式访问成员变量更快,结论:区别不大。。。
        public string Test1()
        {
            long vTickCount = Environment.TickCount;
            for (int i = 0; i < 10000000; i++)
                this.value = i.ToString();
            return string.Format("Have this.: {0} MSEL", Environment.TickCount - vTickCount);
        }
        public string Test2()
        {
            long vTickCount = Environment.TickCount;
            for (int i = 0; i < 10000000; i++)
                value = i.ToString();
            return string.Format("Don't have this.: {0} MSEL", Environment.TickCount - vTickCount);
        }
    }
    class UnitTransClass
    {
        public static double C2F(Class1 value)
        {
            //
摄氏到华氏的转换公式
            return 1.8 * value.C + 32;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Class1 tmpObj = new Class1(37.5);
 
            Console.WriteLine(tmpObj);
 
            Console.WriteLine(tmpObj.Test1());
            Console.WriteLine(tmpObj.Test2());
 
            Console.ReadLine();
        }
    }
}
结果:
37.5 Celsius = 99.5 Fahrenheit
Have this.: 4375 MSEL
Don't have this.: 4406 MSEL  
 
 
10.this  关键字的含义?
答: this  是一个保留字,仅限于构造函数和方法成员中使用 .
在类的构造函数中出现表示对正在构造的对象本身的引用,在类的方法中出现表示对调用该方法的对象的引用,在结构的构造上函数中出现表示对正在构造的结构的引用,在结构的方法中出现表示对调用该方法的结果的引用 .
this  保留字不能用于静态成员的实现里,因为这时对象或结构并未实例化 .  C#  系统中, this  实际上是一个常量,所以不能使用  this++  这样的运算 .
this 
保留字一般用于限定同名的隐藏成员、将对象本身做为参数、声明索引访问器、判断传入参数的对象是否为本身

示例:
using System;
using System.Collections.Generic;
using System.Text;
 
namespace Example10
{
    class Class1
    {
        private double c;
        private string value;
 
        public double C
        {
            get
            {
                return c;
            }
        }
        public Class1(double c)
        {
            //
限定同名的隐藏成员
            this.c = c;
        }
        public Class1(Class1 value)
        {
            //
用对象本身实例化自己没有意义
            if (this != value)
            {
                c = value.C;
            }
        }
        public override string ToString()
        {
            //
将对象本身做为参数
            return string.Format("{0} Celsius = {1} Fahrenheit", c, UnitTransClass.C2F(this));
        }
 
        //
由于好奇,在这做了一个效率测试,想看看到底哪种方式访问成员变量更快,结论:区别不大。。。
        public string Test1()
        {
            long vTickCount = Environment.TickCount;
            for (int i = 0; i < 10000000; i++)
                this.value = i.ToString();
            return string.Format("Have this.: {0} MSEL", Environment.TickCount - vTickCount);
        }
        public string Test2()
        {
            long vTickCount = Environment.TickCount;
            for (int i = 0; i < 10000000; i++)
                value = i.ToString();
            return string.Format("Don't have this.: {0} MSEL", Environment.TickCount - vTickCount);
        }
    }
    class UnitTransClass
    {
        public static double C2F(Class1 value)
        {
            //
摄氏到华氏的转换公式
            return 1.8 * value.C + 32;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Class1 tmpObj = new Class1(37.5);
 
            Console.WriteLine(tmpObj);
 
            Console.WriteLine(tmpObj.Test1());
            Console.WriteLine(tmpObj.Test2());
 
            Console.ReadLine();
        }
    }
}
结果:
37.5 Celsius = 99.5 Fahrenheit
Have this.: 4375 MSEL
Don't have this.: 4406 MSEL 


11.
可以使用抽象函数重写基类中的虚函数吗?
答:可以,但需使用  new  修饰符显式声明,表示隐藏了基类中该函数的实现
示例 :
    class BaseClass
    {
        public virtual void F()
        {
            Console.WriteLine("BaseClass.F");
        }
    }
    abstract class  DeriveClass : BaseClass
    {
        public new abstract void F();
    }

12.
密封类可以有虚函数吗?
答:可以,基类中的虚函数将隐式的转化为非虚函数,但密封类本身不能再增加新的虚函数
示例:
    class BaseClass
    {
        public virtual void F()
        {
            Console.WriteLine("BaseClass.F");
        }
    }
    sealed class DeriveClass : BaseClass
    {
        //
基类中的虚函数 F 被隐式的转化为非虚函数
 
        //
密封类中不能再声明新的虚函数 G
        //public virtual void G()
        //{
        //    Console.WriteLine("DeriveClass.G");
        //}
    }

13.
如果基类中的虚属性只有一个属性访问器,那么继承类重写该属性后可以有几个属性访问器?如果基类中有  get   set  两个呢?
答:如果基类中的虚属性只有一个属性访问器,那么继承类重写该属性后也应只有一个。如果基类中有  get   set  两个属性访问器,那么继承类中可以只有一个也可以同时有两个属性访问器

14.abstract 
可以和  virtual  一起使用吗?可以和  override  一起使用吗?
答: abstract  修饰符不可以和  static virtual   override  修饰符一起使用


15. 接口可以包含哪些成员?
答:接口可以包含属性、方法、索引指示器和事件,但不能包含常量、域、操作符、构造函数和析构函数,而且也不能包含任何静态成员

 

16.
类和结构的区别?
答:
类:类是引用类型在堆上分配,类的实例进行赋值只是复制了引用,都指向同一段实际对象分配的内存 . 类有构造和析构函数 . 类可以继承和被继承
结构:结构是值类型在栈上分配(虽然栈的访问速度比较堆要快,但栈的资源有限放),结构的赋值将分配产生一个新的对象。结构没有构造函数,但可以添加。结构没有析构函数 ,
结构不可以继承自另一个结构或被继承,但和类一样可以继承自接口
示例:
根据以上比较,我们可以得出一些轻量级的对象最好使用结构,但数据量大或有复杂处理逻辑对象最好使用类。
如: Geoemtry GIS  里的一个概论,在  OGC  标准里有定义)  最好使用类,而  Geometry  中点的成员最好使用结构
using System;
using System.Collections.Generic;
using System.Text;
 
namespace Example16
{
    interface IPoint
    {
        double X
        {
            get;
            set;
        }
        double Y
        {
            get;
            set;
        }
        double Z
        {
            get;
            set;
        }
    }
    //
结构也可以从接口继承
    struct Point: IPoint
    {
        private double x, y, z;
        //
结构也可以增加构造函数
        public Point(double X, double Y, double Z)
        {
            this.x = X;
            this.y = Y;
            this.z = Z;
        }
        public double X
        {
            get { return x; }
            set { x = value; }
        }
        public double Y
        {
            get { return x; }
            set { x = value; }
        }
        public double Z
        {
            get { return x; }
            set { x = value; }
        }
    }
    //
在此简化了点状 Geometry 的设计,实际产品中还包含 Project (坐标变换)等复杂操作
    class PointGeometry
    {
        private Point value;
        
        public PointGeometry(double X, double Y, double Z)
        {
            value = new Point(X, Y, Z);
        }
        public PointGeometry(Point value)
        {
            //
结构的赋值将分配新的内存
            this.value = value;
        }
        public double X
        {
            get { return value.X; }
            set { this.value.X = value; }
        }
        public double Y
        {
            get { return value.Y; }
            set { this.value.Y = value; }
        }
        public double Z
       {
            get { return value.Z; }
            set { this.value.Z = value; }
        }
        public static PointGeometry operator +(PointGeometry Left, PointGeometry Rigth)
        {
            return new PointGeometry(Left.X + Rigth.X, Left.Y + Rigth.Y, Left.Z + Rigth.Z);
        }
        public override string ToString()
        {
            return string.Format("X: {0}, Y: {1}, Z: {2}", value.X, value.Y, value.Z);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Point tmpPoint = new Point(1, 2, 3);
 
            PointGeometry tmpPG1 = new PointGeometry(tmpPoint);
            PointGeometry tmpPG2 = new PointGeometry(tmpPoint);
            tmpPG2.X = 4;
            tmpPG2.Y = 5;
            tmpPG2.Z = 6;
 
            //
由于结构是值类型, tmpPG1   tmpPG2  的坐标并不一样
            Console.WriteLine(tmpPG1);
            Console.WriteLine(tmpPG2);
 
            //
由于类是引用类型,对 tmpPG1 坐标修改后影响到了 tmpPG3
            PointGeometry tmpPG3 = tmpPG1;
            tmpPG1.X = 7;
            tmpPG1.Y = 8;
            tmpPG1.Z = 9;
            Console.WriteLine(tmpPG1);
            Console.WriteLine(tmpPG3);
 
            Console.ReadLine();
        }
    }
}
结果:
X: 1, Y: 2, Z: 3
X: 4, Y: 5, Z: 6
X: 7, Y: 8, Z: 9
X: 7, Y: 8, Z: 9 


17.
接口的多继承会带来哪些问题?
答: C#  中的接口与类不同,可以使用多继承,即一个子接口可以有多个父接口。但如果两个父成员具有同名的成员,就产生了二义性(这也正是  C#  中类取消了多继承的原因之一),这时在实现时最好使用显式的声明
示例:
using System;
using System.Collections.Generic;
using System.Text;  
namespace Example17
{
    class Program
    {
        //
一个完整的接口声明示例
        interface IExample
        {
            //
属性
            string P
            {
                get;
                set;
            }
            //
方法
            string F(int Value);
            //
事件
            event EventHandler E;
            //
索引指示器
            string this[int Index]
            {
                get;
                set;
            }
        }
        interface IA
        {
            int Count { get; set;}
        }
        interface IB
        {
            int Count();
        }
        //IC
接口从 IA IB 多重继承
        interface IC : IA, IB
        {
        }
        class C : IC
        {
            private int count = 100;
            //
显式声明实现 IA 接口中的 Count 属性
            int IA.Count
            {
                get { return 100; }
                set { count = value; }
            }
            //
显式声明实现 IB 接口中的 Count 方法
            int IB.Count()
            {
                return count * count;
            }
        }
        static void Main(string[] args)
        {
            C tmpObj = new C();
 
            //
调用时也要显式转换
            Console.WriteLine("Count property: {0}", ((IA)tmpObj).Count);
            Console.WriteLine("Count function: {0}", ((IB)tmpObj).Count());
 
            Console.ReadLine();
        }
    }
}
结果:
Count property: 100
Count function: 10000 

18.
抽象类和接口的区别?
答:
抽象类( abstract class )可以包含功能定义和实现,接口( interface )只能包含功能定义
抽象类是从一系列相关对象中抽象出来的概念,  因此反映的是事物的内部共性;接口是为了满足外部调用而定义的一个功能约定,  因此反映的是事物的外部特性
分析对象,提炼内部共性形成抽象类,用以表示对象本质,即 是什么 ” , 为外部提供调用或功能需要扩充时优先使用接口  


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值