c#入门问题解决(二)

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.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(123); 
  
            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 


posted on 2007-06-08 23:38  子原  阅读(239)  评论(0)    收藏  举报

导航