首页 > 就业 > 笔试

笔试题目(综合版样题)

笔试题目(综合版样题)



笔试题目(综合版样题)

题记:一年一度的招聘黄金时间来临了,本人决定整理C#.Net的资料为本人和园子里的朋友共享!
C#资料(一)
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 一起使用声明为 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
1

5.internal 修饰符起什么作用?

答:internal 修饰符可以用于类型或成员,使用该修饰符声明的类型或成员只能在同一程集内访问接口的成员不能使用 internal 修饰符值得注意的是,如果为 internal 成员加上了 protected 修饰符,这时的访问级别为 internal或 protected。只是看字面意思容易弄错,许多人认为 internal protected 应该是“只有同一个程序集中的子类可以访问”,但其实它表示“同一个程序集中的所有类,以及所有程序集中的子类都可以访问”

示例

Example05Lib 项目的 Class1

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

namespace Example05Lib
{
 public class Class1
 {
 internal String strInternal = null;
 public String strPublic;
 internal protected String strInternalProtected = null;
 }
}

结果
Example05Lib 项目的 Class2 类可以访问到 Class1 的 strInternal 成员,当然也可以访问到 strInternalProtected 成员,因为他们在同一个程序集里


Example05 项目里的 Class3 类无法访问到 Class1 的 strInternal成员,因为它们不在同一个程序集里。但却可以访问到 strInternalProtected 成员,因为 Class3 是 Class1 的继承类


Example05 项目的 Program 类既无法访问到 Class1 的strInternal 成员,也无法访问到 strInternalProtected 成员,因为它们既不在同一个程序集里也不存在继承关系


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 只能是输出 类B 中对该方法的实现:

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];
 }
 }
 }

 //感谢watson hua(http://huazhihao.cnblogs.com/)的指点
 //索引指示器的实质是含参属性,参数并不只限于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.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 修饰符显式声明,表示隐藏了基类中该函数的实现

或增加 override 修饰符,表示抽象重写了基类中该函数的实现

示例:

 class BaseClass
 {
 public virtual void F()
 {
 Console.WriteLine("BaseClass.F");
 }
 }
 abstract class DeriveClass1 : BaseClass
 {
 public abstract new void F();
 }

 //感谢watson hua(http://huazhihao.cnblogs.com/)的指点
 //是他提醒了我还可以用这种方法抽象重写基类的虚方法
 abstract class DeriveClass2 : BaseClass
 {
 public abstract override 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.什么是属性访问器?

答:属性访问器(Property Accessor),包括 get 访问器和 set 访问器分别用于字段的读写操作
其设计目的主要是为了实现面向对象(OO)中的封装思想。根据该思想,字段最好设为private,一个精巧的类最好不要直接把字段设为公有提供给客户调用端直接访问
另外要注意属性本身并不一定和字段相联系

14.abstract 可以和 virtual 一起使用吗?可以和 override 一起使用吗?

答:abstract 修饰符不可以和 static、virtual 修饰符一起使用

abstract 修饰符可以和 override 一起使用,参见第11点

示例:

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

namespace Example14
{
 class BaseClass
 {
 public virtual void F()
 {
 Console.WriteLine("BaseClass.F");
 }
 }
 abstract class DeriveClass1 : BaseClass
 {
 //在这里, abstract是可以和override一起使用的
 public abstract override void F();
 }
 class Program
 {
 static void Main(string[] args)
 {
 }
 }
}

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)只能包含功能定义
抽象类是从一系列相关对象中抽象出来的概念, 因此反映的是事物的内部共性;接口是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性
分析对象,提炼内部共性形成抽象类,用以表示对象本质,即“是什么”
为外部提供调用或功能需要扩充时优先使用接口

19.别名指示符是什么?

答:通过别名指示符我们可以为某个类型起一个别名
主要用于解决两个命名空间内有同名类型的冲突或避免使用冗余的命名空间
别名指示符在所有命名空间最外层定义,作用域为整个单元文件。如果定义在某个命名空间内,那么它只在直接隶属的命名空间内起作用

示例:

Class1.cs:

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

namespace com.nblogs.reonlyrun.CSharp25QExample.Example19.Lib01
{
 class Class1
 {
 public override string ToString()
 {
 return "com.nblogs.reonlyrun.CSharp25QExample.Example19.Lib01's Class1";
 }
 }
}

Class2.cs:

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

namespace com.nblogs.reonlyrun.CSharp25QExample.Example19.Lib02
{
 class Class1
 {
 public override string ToString()
 {
 return "com.nblogs.reonlyrun.CSharp25QExample.Example19.Lib02's Class1";
 }
 }
}

主单元(Program.cs):

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

//使用别名指示符解决同名类型的冲突
//在所有命名空间最外层定义,作用域为整个单元文件
using Lib01Class1 = com.nblogs.reonlyrun.CSharp25QExample.Example19.Lib01.Class1;
using Lib02Class2 = com.nblogs.reonlyrun.CSharp25QExample.Example19.Lib02.Class1;

namespace Example19
{
 namespace Test1
 {
 //Test1Class1在Test1命名空间内定义,作用域仅在Test1之内
 using Test1Class1 = com.nblogs.reonlyrun.CSharp25QExample.Example19.Lib01.Class1;

 class Class1
 {
 //Lib01Class1和Lib02Class2在这可以正常使用
 Lib01Class1 tmpObj1 = new Lib01Class1();
 Lib02Class2 tmpObj2 = new Lib02Class2();
 //TestClass1在这可以正常使用
 Test1Class1 tmpObj3 = new Test1Class1();
 }
 }
 namespace Test2
 {
 using Test1Class2 = com.nblogs.reonlyrun.CSharp25QExample.Example19.Lib01.Class1;

 class Program
 {
 static void Main(string[] args)
 {
 //Lib01Class1和Lib02Class2在这可以正常使用
 Lib01Class1 tmpObj1 = new Lib01Class1();
 Lib02Class2 tmpObj2 = new Lib02Class2();

 //注意这里,TestClass1在这不可以正常使用。
 //因为,在Test2命名空间内不能使用Test1命名空间定义的别名
 //Test1Class1 tmpObj3 = new Test1Class1();
 
 //TestClass2在这可以正常使用
 Test1Class2 tmpObj3 = new Test1Class2();

 Console.WriteLine(tmpObj1);
 Console.WriteLine(tmpObj2);
 Console.WriteLine(tmpObj3);

 Console.ReadLine();
 }
 }
 }
}

结果:

com.nblogs.reonlyrun.CSharp25QExample.Example19.Lib01's Class1
com.nblogs.reonlyrun.CSharp25QExample.Example19.Lib02's Class1
com.nblogs.reonlyrun.CSharp25QExample.Example19.Lib01's Class1

20.如何手工释放资源?

答:.NET 平台在内存管理方面提供了GC(Garbage Collection),负责自动释放托管资源和内存回收的工作。但在以下两种情况需要我们手工进行资源释放:一、由于它无法对非托管资源进行释放,所以我们必须自己提供方法来释放对象内分配的非托管资源,比如你在对象的实现代码中使用了一个COM对象;二、你的类在运行是会产生大量实例(象 GIS 中的Geometry),必须自己手工释放这些资源以提高程序的运行效率

最理想的办法是通过实现一个接口显式的提供给客户调用端手工释放对象,System 命名空间内有一个 IDisposable 接口,拿来做这事非常合适,省得我们自己再声明一个接口了

示例:

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

namespace Example20
{
    class Program
    {
        class Class1 : IDisposable
        {
            //析构函数,编译后变成 protected void Finalize(),GC会在回收对象前会调用调用该方法
            ~Class1()
            {
                Dispose(false);
            }

            //通过实现该接口,客户可以显式地释放对象,而不需要等待GC来释放资源,据说那样会降低效率
            void IDisposable.Dispose()
            {
                Dispose(true);
            }

            //将释放非托管资源设计成一个虚函数,提供在继承类中释放基类的资源的能力
            protected virtual void ReleaseUnmanageResources()
            {
                //Do something...
            }

            //私有函数用以释放非托管资源
            private void Dispose(bool disposing)
            {
                ReleaseUnmanageResources();

                //为true时表示是客户显式调用了释放函数,需通知GC不要再调用对象的Finalize方法
                //为false时肯定是GC调用了对象的Finalize方法,所以没有必要再告诉GC你不要调用我的Finalize方法啦
                if (disposing)
                {
                    GC.SuppressFinalize(this);
                }
            } 
        }
        static void Main(string[] args)
        {
            //tmpObj1没有手工释放资源,就等着GC来慢慢的释放它吧
            Class1 tmpObj1 = new Class1();

            //tmpObj2调用了Dispose方法,传说比等着GC来释放它效率要调一些
            //个人认为是因为要逐个对象的查看其元数据,以确认是否实现了Dispose方法吧
            //当然最重要的是我们可以自己确定释放的时间以节省内存,优化程序运行效率
            Class1 tmpObj2 = new Class1();
            ((IDisposable)tmpObj2).Dispose();
        }
    }
}

21.P/Invoke是什么?

答:在受控代码与非受控代码进行交互时会产生一个事务(transition),这通常发生在使用平台调用服务(Platform Invocation Services),即P/Invoke
如调用系统的 API 或与 COM 对象打交道,通过 System.Runtime.InteropServices 命名空间
虽然使用 Interop 非常方便,但据估计每次调用事务都要执行 10 到 40 条指令,算起来开销也不少,所以我们要尽量少调用事务.如果非用不可,建议本着一次调用执行多个动作,而不是多次调用每次只执行少量动作的原则

22.StringBuilder 和 String 的区别?

答:String 在进行运算时(如赋值、拼接等)会产生一个新的实例,而 StringBuilder则不会。所以在大量字符串拼接或频繁对某一字符串进行操作时最好使用 StringBuilder,不要使用 String
另外,对于 String 我们不得不多说几句:
1.它是引用类型,在堆上分配内存
2.运算时会产生一个新的实例
3.String 对象一旦生成不可改变(Immutable)
4.定义相等运算符(==!=)是为了比较 String 对象(而不是引用)的值

示例:

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

namespace Example22
{
 class Program
 {
 static void Main(string[] args)
 {
 const int cycle = 10000;

 long vTickCount = Environment.TickCount;
 String str = null;
 for (int i = 0; i < cycle; i++)
 str += i.ToString();
 Console.WriteLine("String: {0} MSEL", Environment.TickCount - vTickCount);

 vTickCount = Environment.TickCount;
 //看到这个变量名我就生气,奇怪为什么大家都使它呢? :)
 StringBuilder sb = new StringBuilder();
 for (int i = 0; i < cycle; i++)
 sb.Append(i);
 Console.WriteLine("StringBuilder: {0} MSEL", Environment.TickCount - vTickCount);

 string tmpStr1 = "A";
 string tmpStr2 = tmpStr1;
 Console.WriteLine(tmpStr1);
 Console.WriteLine(tmpStr2);
 //注意后面的输出结果,tmpStr1的值改变并未影响到tmpStr2的值
 tmpStr1 = "B";
 Console.WriteLine(tmpStr1);
 Console.WriteLine(tmpStr2);

 Console.ReadLine();
 }
 }
}

结果:
String: 375 MSEL
StringBuilder: 16 MSEL
A
A
B
A

23.explicit 和 implicit 的含义?

答:explicit 和 implicit 属于转换运算符,如用这两者可以让我们自定义的类型支持相互交换

explicti 表示显式转换,如从 A -> B必须进行强制类型转换(B = (B)A)
implicit 表示隐式转换,如从 B -> A 只需直接赋值(A = B)
隐式转换可以让我们的代码看上去更漂亮、更简洁易懂,所以最好多使用 implicit 运算符。不过!如果对象本身在转换时会损失一些信息(如精度),那么我们只能使用 explicit 运算符,以便在编译期就能警告客户调用端

示例:

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

namespace Example23
{
    class Program
    {
        //本例灵感来源于大话西游经典台词“神仙?妖怪?”--主要是我实在想不出什么好例子了
        class Immortal
        {
            public string name;
            public Immortal(string Name)
            {
                name = Name;
            }
            public static implicit operator Monster(Immortal value)
            {
                return new Monster(value.name + ":神仙变妖怪?偷偷下凡即可。。。");
            }
        }
        class Monster
        {
            public string name;
            public Monster(string Name)
            {
                name = Name;
            }
            public static explicit operator Immortal(Monster value)
            {
                return new Immortal(value.name + ":妖怪想当神仙?再去修炼五百年!");
            }
        }
        static void Main(string[] args)
        {
            Immortal tmpImmortal = new Immortal("紫霞仙子");
            //隐式转换
            Monster tmpObj1 = tmpImmortal;
            Console.WriteLine(tmpObj1.name);

            Monster tmpMonster = new Monster("孙悟空");
            //显式转换
            Immortal tmpObj2 = (Immortal)tmpMonster;
            Console.WriteLine(tmpObj2.name);

            Console.ReadLine();
        }
    }
}

结果:
紫霞仙子:神仙变妖怪?偷偷下凡即可。。。
孙悟空:妖怪想当神仙?再去修炼五百年!

24.params 有什么用?

答:params 关键字在方法成员的参数列表中使用,为该方法提供了参数个数可变的能力
它在只能出现一次并且不能在其后再有参数定义,之前可以

示例:

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

namespace ConsoleApplication1
{
    class App
    {
        //第一个参数必须是整型,但后面的参数个数是可变的。
        //而且由于定的是object数组,所有的数据类型都可以做为参数传入
        public static void UseParams(int id, params object[] list)
        {
            Console.WriteLine(id);
            for (int i = 0; i < list.Length; i++)
            {
                Console.WriteLine(list[i]);
            }
        }

        static void Main()
        {
            //可变参数部分传入了三个参数,都是字符串类型
            UseParams(1, "a", "b", "c");
            //可变参数部分传入了四个参数,分别为字符串、整数、浮点数和双精度浮点数数组
            UseParams(2, "d", 100, 33.33, new double[] { 1.1, 2.2 });

            Console.ReadLine();
        }
    }
}

结果:
1
a
b
c
2
d
100
33.33
System.Double[]

25.什么是反射?

答:反射,Reflection,通过它我们可以在运行时获得各种信息,如程序集、模块、类型、字段、属性、方法和事件

通过对类型动态实例化后,还可以对其执行操作

简单来说就是用string可以在runtime为所欲为的东西,实际上就是一个.net framework内建的万能工厂

一般用于插件式框架程序和设计模式的实现,当然反射是一种手段可以充分发挥其能量来完成你想做的任何事情(前面好象见过一位高人用反射调用一个官方类库中未说明的函数。。。)

示例:

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

namespace Example25Lib
{
    public class Class1
    {
        private string name;
        private int age;

        //如果显式的声明了无参数构造函数,客户端只需要用程序集的CreateInstance即可实例化该类
        //在此特意不实现,以便在客户调用端体现构造函数的反射实现
        //public Class1()
        //{
        //}
        public Class1(string Name, int Age)
        {
            name = Name;
            age = Age;
        }
        public void ChangeName(string NewName)
        {
            name = NewName;
        }
        public void ChangeAge(int NewAge)
        {
            age = NewAge;
        }
        public override string ToString()
        {
            return string.Format("Name: {0}, Age: {1}", name, age);
        }
    }
}

反射实例化对象并调用其方法,属性和事件的反射调用略去

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

//注意添加该反射的命名空间
using System.Reflection;

namespace Example25
{
    class Program
    {
        static void Main(string[] args)
        {
            //加载程序集
            Assembly tmpAss = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "Example25Lib.dll");

            //遍历程序集内所有的类型,并实例化
            Type[] tmpTypes = tmpAss.GetTypes();
            foreach (Type tmpType in tmpTypes)
            {
                //获取第一个类型的构造函数信息
                ConstructorInfo[] tmpConsInfos = tmpType.GetConstructors();
                foreach (ConstructorInfo tmpConsInfo in tmpConsInfos)
                {
                    //为构造函数生成调用的参数集合
                    ParameterInfo[] tmpParamInfos = tmpConsInfo.GetParameters(); 
                    object[] tmpParams = new object[tmpParamInfos.Length];
                    for (int i = 0; i < tmpParamInfos.Length; i++)
                    {
                        tmpParams[i] = tmpAss.CreateInstance(tmpParamInfos[i].ParameterType.FullName);
                        if (tmpParamInfos[i].ParameterType.FullName == "System.String")
                        {
                            tmpParams[i] = "Clark";
                        }
                    }

                    //实例化对象
                    object tmpObj = tmpConsInfo.Invoke(tmpParams);
                    Console.WriteLine(tmpObj);

                    //获取所有方法并执行
                    foreach (MethodInfo tmpMethod in tmpType.GetMethods())
                    {
                        //为方法的调用创建参数集合
                        tmpParamInfos = tmpMethod.GetParameters();
                        tmpParams = new object[tmpParamInfos.Length];
                        for (int i = 0; i < tmpParamInfos.Length; i++)
                        {

tmpParams[i] = tmpAss.CreateInstance

(tmpParamInfos[i].ParameterType.FullName);

                            if (tmpParamInfos[i].ParameterType.FullName == "System.String")
                            {
                                tmpParams[i] = "Clark Zheng";
                            }
                            if (tmpParamInfos[i].ParameterType.FullName == "System.Int32")
                            {
                                tmpParams[i] = 27;
                            }
                        }
                        tmpMethod.Invoke(tmpObj, tmpParams);
                    }

                    //调用完方法后再次打印对象,比较结果
                    Console.WriteLine(tmpObj);
                }
            }

            Console.ReadLine();
        }
    }
}

结果:
Name: Clark, Age: 0
Name: Clark Zheng, Age: 27
总结:通过以上我们可以理解C#中难以理解的概念和示例代码.
软件测试题目
一、 判断题 (每题2分,20)

1、软件测试就是为了验证软件功能实现的是否正确,是否完成既定目标的活动,所以软件测试在软件工程的后期才开始具体的工作。 (初级) ×

2、发现错误多的模块,残留在模块中的错误也多。( ) (初级)

3、测试人员在测试过程中发现一处问题,如果问题影响不大,而自己又可以修改,应立即将此问题正确修改,以加快、提高开发的进程。( × )(初级)

4、单元测试通常应该先进行人工走查,再以白盒法为主,辅以黑盒法进行动态测试。

)(中级)

5、功能测试是系统测试的主要内容,检查系统的功能、性能是否与需求规格说明相同。( )(中级)

6、软件质量管理即QMQAQC构成,软件测试属于QC的核心工作内容。(√)(高级)

7、软件测试只能发现错误,但不能保证测试后的软件没有错误。(√)

8、软件就是程序。(X)

9、测试只要做到语句覆盖和分支覆盖,就可以发现程序中的所有错误。(X)

10I18N测试是指对产品做出具有国际性的规划,而L10N测试则是指对软件做出符合本地需求更改工作。(√)【高级】

.NET工程(三)

1.面向对象的思想主要包括什么?

继承多态封装

封装:用抽象的数据类型将数据和基于数据的操作封装在一起,数据被保护在抽象数据类型内部。

继承:子类拥有父类的所有数据和操作。

多态:一个程序中同名的不同方法共存的情况。

有两种形式的多态–重载与重写。

2.什么是ASP.net中的用户控件

用户控件就是.ascx扩展名的东西喽,可以拖到不同的页面中调用,以节省代码.比如登陆可能在多个页面上有,就可以做成用户控件,但是有一个问题就是用户控件拖到不同级别的目录下后里面的图片等的相对路径会变得不准确,需要自已写方法调整.

问这样的问题,一般是迷惑你.因为新手还是分不清楚用户控件和服务器控件(也称自定义控件)..用户控件一般用在内容多为静态,或者少许会改变的情况下..用的比较大..类似ASP中的include..但是功能要强大的多..

C#中,string str = null string str = “”的区别。
答:string str = null 是不给他分配内存空间,string str = "" 给它分配长度为空字符串的内存空间
请详述在dotnet中类(class)与结构(struct)的异同
Class可以被实例化,属于引用类型,是分配在内存的堆上的,Struct属于值类型,是分配在内存的栈上的.

DataReader和DataSet的异同
DataReader和DataSet最大的区别在于,DataReader使用时始终占用SqlConnection,在线操作数据库..任何对SqlConnection的操作都会引发DataReader的异常..因为DataReader每次只在内存中加载一条数据,所以占用的内存是很小的..因为DataReader的特殊性和高性能.所以DataReader是只进的..你读了第一条后就不能再去读取第一条了..
DataSet则是将数据一次性加载在内存中.抛弃数据库连接..读取完毕即放弃数据库连接..因为DataSet将数据全部加载在内存中.所以比较消耗内存...但是确比DataReader要灵活..可以动态的添加行,列,数据.对数据库进行回传更新操作.

8.C#中的接口和类有什么异同。

接口和类都是类,不同的事,接口只包含方法或属性的声明,不包含具体实现方法的代码,接口可以实现多继承,而类只能是单继承,继承接口的类必须实现接口中声明的方法或属性。接口主要定义一种规范,统一调用方法,在大型项目中接口正发挥日益重要的作用

类是方法功能的实现和集合,接口是规范类.约束类.
接口,是可以多继承,类只有单继承.接口强调了你必须实现,而没有具本实现的方法和虚类有点相似

Override与重载有什么区别?
一个是重写父类函数,一个是同一个函数的几种形式

触发器的作用

触发器可以查询其它表,而且可以包含复杂的 SQL 语句。它们主要用于强制复杂的业务规则或要求。触发器还有助于强制引用完整性,以便在添加、更新或删除表中的行时保留表之间已定义的关系。
保证数据库操作变更能接到通知

<%# %> 和 <% %> 有什么区别?
<%# %>表示绑定的数据源
<% %>是服务器端代码块

常见的设计模式

抽象工厂模式、适配器模式、外观模式 command命令模式,桥接模式,组合模式,装饰模式,状态模式,备忘录模式等。
??软件设计模式太多,就我的理解简单说一下最常见的MVC模式。
??MVC模式是1996年由Buschmann提出的:
??模型(Model):就是封装数据和所有基于对这些数据的操作。
??视图(View):就是封装的是对数据显示,即用户界面。
??控制器(Control):就是封装外界作用于模型的操作和对数据流向的控制等。

??

3.什么叫应用程序域?什么是受管制的代码?什么是强类型系统?什么是装箱和拆箱?什么是重载?CTSCLSCLR分别作何解释?

4.列举一下你所了解的XML技术及其应用

5.值类型和引用类型的区别?写出C#的样例代码。

dotnet中有两大类数据类型,即值类型和引用类型,值类型存贮在栈中,而引用类型存贮在动态的堆中,栈是先进先出的有系统管理的空间,而堆是由应用程序控制的可随时申请和释放该空间,在Donnet中一般情况下有垃圾收集器处理,他们的不同导致在编程上的不同。
例: StringBuilder a=new StringBuilder();//StringBuilder的一个首地址传给a
StringBuilder b=a;//
StringBuilder的一个首地址传给b
b.Append("mxh");
Console.WriteLine(a);
a=null;
Console.WriteLine(b);
输出结果:mxh
mxh
"a=null"
的意思是:a的引用置为空但此时StringBuilder的堆空间并没有被释放,因此在此之后,输出b时,仍然可以输出mxh

6.ADO.net中常用的对象有哪些?分别描述一下。

7.如何理解委托?

C# 中的委托类似于 C C++ 中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与 C C++ 中的函数指针不同,委托是面向对象、类型安全的,并且是安全的。

9.net中读写数据库需要用到哪些类?他们的作用

10.UDP连接和TCP连接的异同。

11.ASP.net的身份验证方式有哪些?分别是什么原理?

window验证:为每个用户开启window帐号,验证其身份.安全性较高.
forms
验证:为每个登陆用户写入一个身份验证票据..web使用最广的验证方式..灵活方便.

12.进程和线程分别怎么理解?

13.什么是code-Behind技术。

新建一个VS.NET下的项目..看到ASPX,RESXCS三个后缀的文件了吗??这个就是代码分离.实现了HTML代码和服务器代码分离.方便代码编写和整理.

14.活动目录的作用。

活动目录是window2000的最重要的功能.可以将用户信息全部集成起来,登陆以后可以访问多个不同的网络服务..

.

15..net中读写XML的类都归属于哪些命名空间?

System.XML

16.解释一下UDDIWSDL的意义及其作用。

17.什么是SOAP,有哪些应用。

simple object access protocal,简单对象接受协议.xml为基本编码结构,建立在已有通信协议上(http,不过据说ms在搞最底层的架构在tcp/ip上的soap)的一种规范
是微软大力推广的Web Service使用的协议..

18.如何部署一个ASP.net页面。

19.如何理解.net中的垃圾回收机制。

如果发现内存不够,则垃圾回收器,将全部对象作为无效对象(被回收对象),然后先将全局变量,static,处于活动中的局部变量,以及当前CG指针指向的对象放入一个表中.然后
会搜索新列表中的对象所引用的对象.加入列表中,其他没有被加入列表的对象都会被回收.

20.常用的调用webservice方法有哪些?

我一般用的是WSDL..或者web引用..

21列举一下你所了解的XML技术及其应用
.xml可以用来做网页(xslt) xml可以当作数据库 xml可以用来保存对象的系列化
xml用于配置,用于保存静态数据类型.接触XML最多的是web Services..config

C# property attribute的区别,他们各有什么用处,这种机制的好处在哪里?
一个是属性,用于存取类的字段,一个是特性,用来标识类,方法等的附加性质

C#可否对内存进行直接的操作?
可以

维护数据库的完整性、一致性、你喜欢用触发器还是自写业务逻辑?为什么

触发器,性能好,事务性

ADONET相对于ADO等主要有什么改进?

新增dataset等,不需要随时保持连接,性能提高

ASPNETASP相比,主要有哪些进步?
asp解释型,aspx编译型,性能提高,有利于保护源码

C#中的委托是什么?事件是不是一种委托?
委托是一种安全的函数指针,事件是一种消息机制

你对XMLHTTPWEBSERVICE 了解吗?简单描述其特点、作用
xmlhttp可以主动获取远端web代码,类似HttpWebRequest

接口和抽象类有什么区别?你选择使用接口和抽象类的依据是什么?
接口用于规范,抽象类用于共性。

存储过程和函数的区别
存储过程是编译好的存储在数据库的操作,函数不用说了.

事务是什么?
具有原子性特点

游标的作用?如何知道游标已经到了最后?
指示当前记录的位置,检查NULL

触发器分为事前触发和事后触发,这两种触发有和区别。语句级触发和行级触发有何区别。
一个是操作前,一个是操作后

请说明在.net中常用的几种页面间传递参数的方法,并说出他们的优缺点
session(viewstate) 简单,但易丢失
application 全局
cookie 简单,但可能不支持,可能被伪造
input type="hidden" 简单,可能被伪造
url参数 简单,显示于地址栏,长度有限
数据库 稳定,安全,但性能相对弱

请说明.net中的错误处理机制,并举例
try catch final

请说出强名的含义
具有自己的key,可以在GAC为公用

请列出c#中几种循环的方法,并指出他们的不同
for wile foreach

请指出.net中所有类型的基类
object

请指出GAC的含义
全局程序集缓存

值类型与引用类型有什么区别?
值和指针的区别

怎样理解静态变量?
所有实例公用一个的变量

向服务器发送请求有几种方式?
get post

如果在一个B/S结构的系统中需要传递变量值,但是又不能使用Session、Cookie、Application,您有几种方法进行处理?
input type=""
url
数据库

用.net做B/S结构的系统,您是用几层结构来开发,每一层之间的关系以及为什么要这样分层?
三层,表现,逻辑,数据, 安全性,维护性

软件开发过程一般有几个阶段?每个阶段的作用?
需求分析,架构设计,代码编写,QA,部署

通过超链接怎样传递中文参数?
URLEncode URLDecode

请编程遍历页面上所有TextBox控件并给它赋值为string.Empty
foreach

有哪几种方法可以实现一个类存取另外一个类的成员函数及属性,并请举列来加以说明和分析.
同一个名称控件直接,或者反射

如果需记录类的实例个数,该如何实现,请写一个简单的类于以证明.
const static int classNum=0;
classNum++;

A类是B类的基类,并且都有自己的构造,析构函数,请举例证明B类从实例化到消亡过程中构造,析构函数的执行过程.
构造先父后子,析够反之

需要实现对一个字符串的处理,首先将该字符串首尾的空格去掉,如果字符串中间还有连续空格的话,仅保留一个空格,即允许字符串中间有多个空格,但连续的空格数不可超过一个.
string inputStr=" xx xx ";
inputStr=Regex.Replace(inputStr.Trim()," *"," ");

在c#中using和new这两个关键字有什么意义,请写出你所知道的意义?

using 指令 和语句 new 创建实例 new 隐藏基类中方法
using 引入名称空间或者使用非托管资源
new 新建实例或者隐藏父类方法

谈谈类和结构的区别
类是引用类型、结构是值类型

什么叫做SQL注入,如何防止?请举例说明。
利用sql关键字对网站进行攻击。过滤关键字'等

下面这段代码输出什么?为什么?
int i=5;
int j=5;
if (Object.ReferenceEquals(i,j))
Console.WriteLine("Equal");
else
Console.WriteLine("Not Equal");

写一个实现对一段字符串翻转的方法,附加一些条件,如其中包括“,”、“.”,对其设计测试用例
inputStr=inputStr.ToCharArray().Reverse().ToString();

什么是反射?
动态获取程序集信息

用Singleton如何写设计模式
static属性里面new ,构造函数private

C#中的垃圾回收机制是怎样的?
三个generation,当每个generation内存满了的时候检查引用,无引用就回收内存

什么是Application Pool?
Web应用,类似Thread Pool,提高并发性能

链表和数组的区别,各有什么优缺点.
一个可以动态增长,一个固定(VB中可以Redim),性能数组教好

什么是友元函数?
friendly声明,可以访问protect级别方法

什么是虚函数?
可以被重写

什么是抽象函数?
必须被重写

什么是内存泄漏,怎样最简单的方法判断被存泄漏 ?
C++,C中忘了释放内存,内存不会再次分配

1SQL Server的两种索引是何形式?索引的作用?索引的优缺点
cluster和非cluster,加速查找,占用额外控件,维护索引耗费时间

什么是XML?
可扩展标记语言,可以做配置文件,可以传输数据,可以存储数据

简述 private、 protected、 public、 internal 修饰符的访问权限。
private : 私有成员, 在类的内部才可以访问。
protected : 保护成员,该类内部和继承类中可以访问。
public : 公共成员,完全公开,没有访问限制。
internal: 在同一命名空间内可以访问。

进程和线程的区别

进程是系统进行资源分配和调度的单位;线程是CPU调度和分派的单位,一个进程可以有多个线程,这些线程共享这个进程的资源。

成员变量和成员函数前加static的作用

它们被称为常成员变量和常成员函数,又称为类成员变量和类成员函数。分别用来反映类的状态。比如类成员变量可以用来统计类实例的数量,类成员函数负责这种统计的动作。

malloc和new的区别

new是C++的关键字。malloc在分配内存时必须按给出的字节分配,new可以按照对象的大小自动分配,并且能调用构造函数。可以说new是对象的对象,而malloc不是。本质上new分配内存时,还会在实际内存块的前后加上附加信息,所以new所使用的内存大小比malloc多。

堆和栈的区别

栈:由编译器自动分配、释放。在函数体中定义的变量通常在栈上。
堆:一般由程序员分配释放。用new、malloc等分配内存函数分配得到的就是在堆上。
栈是机器系统提供的数据结构,而堆则是C/C++函数库提供的。
栈是系统提供的功能,特点是快速高效,缺点是有限制,数据不灵活;而栈是函数库提供的功能,特点是灵活方便,数据适应面广泛,但是效率有一定降低。栈是系统数据结构,对于进程/线程是唯一的;堆是函数库内部数据结构,不一定唯一。不同堆分配的内存无法互相操作。栈空间分静态分配和动态分配两种。静态分配是编译器完成的,比如自动变量(auto)的分配。动态分配由alloca函数完成。栈的动态分配无需释放(是自动的),也就没有释放函数。为可移植的程序起见,栈的动态分配操作是不被鼓励的!堆空间的分配总是动态的,虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存/释放内存匹配是良好程序的基本要素。

在.Net中,类System.Web.UI.Page 可以被继承么?
可以

你觉得ASP.NET 2.0(VS2005)和你以前使用的开发工具(.Net 1.0或其他)有什么最大的区别?你在以前的平台上使用的哪些开发思想(pattern / architecture)可

1 ASP.NET 2.0 把一些代码进行了封装打包,所以相比1.0相同功能减少了很多代码.
2 同时支持代码分离和页面嵌入服务器端代码两种模式,以前1.0版本,.NET提示帮助只有在分离的代码文件,无法在页面嵌入服务器端代码获得帮助提示,
3 代码和设计界面切换的时候,2.0支持光标定位.这个我比较喜欢
4 在绑定数据,做表的分页.UPDATE,DELETE,等操作都可以可视化操作,方便了初学者
5, 在ASP.NET中增加了40多个新的控件,减少了工作量

.net的错误处理机制是什么
.net错误处理机制采用try->catch->finally结构,发生错误时,层层上抛,直到找到匹配的Catch为止。

重载与覆盖的区别
1、方法的覆盖是子类和父类之间的关系,是垂直关系;方法的重载是同一个类中方法之间的关系,是水平关系。
2、覆盖只能由一个方法,或只能由一对方法产生关系;方法的重载是多个方法之间的关系。
3、覆盖要求参数列表相同;重载要求参数列表不同。
4、覆盖关系中,调用那个方法体,是根据对象的类型(对象对应存储空间类型)来决定;重载关系,是根据调用时的实参表与形参表来选择方法体的。

简要谈一下您对微软.NET 构架下remoting和webservice两项技术的理解以及实际中的应用。
WS主要是可利用HTTP,穿透防火墙。而Remoting可以利用TCP/IP,二进制传送提高效率。

C#中的委托是什么?事件是不是一种委托?
委托是一种安全的函数指针,事件是一种消息机制

new有几种用法
第一种:new Class();
第二种:覆盖方法
public new XXXX(){}
第三种:new 约束指定泛型类声明中的任何类型参数都必须有公共的无参数构造函数。
如何把一个array复制到arrayList里
foreach( object o in array )arrayList.Add(o);
datagrid.datasouse可以连接什么数据源
dataset,datatable,dataview , IList
概述反射和序列化
反射:程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性
序列化:序列化是将对象转换为容易传输的格式的过程。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。在另一端,反序列化将从该流重新构造对象。
概述o/r mapping 的原理>
利用反射,配置 将类于数据库表映射
用sealed修饰的类有什么特点
sealed 修饰符用于防止从所修饰的类派生出其它类。如果一个密封类被指定为其他类的基类,则会发生编译时错误。
密封类不能同时为抽象类。
sealed 修饰符主要用于防止非有意的派生,但是它还能促使某些运行时优化。具体说来,由于密封类永远不会有任何派生类,所以对密封类的实例的虚拟函数成员的调用可以转换为非虚拟调用来处理。

什么叫应用程序域?什么是受管制的代码?什么是强类型系统?什么是装箱和拆箱?什么是重载?CTS、CLS和CLR分别作何解释
答:装箱就是把值类型转成引用类型,从MS IL角度看好像是boxing,没记错的话是把值从堆栈转到堆中.拆箱相反,重载就是指一个方法名同,参数个数不同,返回值可以相同的方法.CLR是通用语言运行时,其它的不清楚.
如何理解委托?
答:据说相当于函数指针,定义了委托就可以在不调用原方法名称的情况下调用那个方法.
委托具有以下特点:
委托类似于 C++ 函数指针,但它是类型安全的。
委托允许将方法作为参数进行传递。
委托可用于定义回调方法。
委托可以链接在一起;例如,可以对一个事件调用多个方法。
方法不需要与委托签名精确匹配。有关更多信息,请参见协变和逆变。
C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。
UDP连接和TCP连接的异同。
前者只管传,不管数据到不到,无须建立连接.后者保证传输的数据准确,须要连结.
进程和线程分别怎么理解?
进程是老子,线程是儿子,没有老子就没有儿子,一个老子可以有多个儿子.一个儿子可以成为别人的儿子,一个老子也可以为别的老子生儿子.
什么是SOAP,有哪些应用
答:SOAP(Simple Object Access Protocol )简单对象访问协议是在分散或分布式的环境中交换信息并执行远程过程调用的协议,是一个基于XML的协议。使用SOAP,不用考虑任何特定的传输协议(最常用的还是HTTP协议),可以允许任何类型的对象或代码,在任何平台上,以任何一直语言相互通信。这种相互通信采用的是XML格式的消息.

1. 填空: (1)面向对象的语言具有___继承性、封装性、多态性。

(2)能用foreach遍历访问的对象需要实现 IEnumerable接口或声明GetEnumerator 方法的类型

(3)列举ADO.net中的五个主要对象

CommandConnectionDataSetDataAdapterDataReader

2. 不定项选择

(1) 以下叙述正确的是:

A. 接口中可以有虚方法。 B. 一个类可以实现多个接口。

C. 接口不能被实例化。 D. 接口中可以包含已实现的方法。

(2) 从数据库读取记录,你可能用到的方法有:

A. ExecuteNonQuery B. ExecuteScalar

C. Fill D. ExecuteReader

3. 简述 private protected public internal 修饰符的访问权限

4. 写出一条Sql语句:取出表A中第31到第40记录(SQLServer, 以自动增长的ID作为主键,注意:ID

可能不是连续的。)

5 .列举ASP.NET 页面之间传递值的几种方式。

三种比较常见的方式,一种是可以通过用QueryString来传送相应的值,再一种是通过session变量来传送相应的值,还有就是通过Server.Transfer方法来实现

(1)queryString
(2)session
(3)cookie
(4)server.transfer
(5)hidden control/view state
(6)static member.
(7)cache
(8)application
(9)DataBase
(10)xml or other Files
(11)XMLHTTP or Hidden iFrame/frame
(12)Context.user.identity

我正在做一个通用提示叶面,所有叶面出现问题都要,传递几个变量字符串到同一个叶面 hitMsg.aspx 变量字符串包括提示语言,即将跳转的叶面,跳转时间。在1-11种方案中哪个更好些?
(1)queryString
的毛病是无法传递很长字符串,比如系统错误信息往往就一整个屏幕。
(2)session
的毛病是不能过多使用,依赖Cookie,容易丢失。
(3)cookie
的毛病是依赖客户端设置,不可靠。
(4)server.transfer
的毛病是接收叶面要为发送叶面准备好,只能定制专门一个叶面接受定制好的叶面。
不能是一个叶面接受任何叶面。
(5)hidden control/view state
只能传递本页。除非特殊制作。
(6)static member.
无法保证线程安全,可能会此处栽瓜他处得豆。
(7)cache
不适合使用一次就扔的变量。
(8)application
全局的,开销大。
(9)DataBase
全局固化的,开销更大,除非做日志跟踪。
(10)xml or other Files
全局固化的,开销大,除非做日志跟踪。
(11)XMLHTTP or Hidden iFrame/frame
,做这个过于烦琐。
(12)Context
这个占用了用户id,不适合做这个。

6. 写出程序的输出结果

class Class1{

private string str = "Class1.str";

private int i = 0;

static void StringConvert(string str){

str = "string being converted.";

}

static void StringConvert(Class1 c){

c.str = "string being converted.";

}

static void Add(int i){

i++;

}

static void AddWithRef(ref int i){

i++;

}

static void Main(){

int i1 = 10;

int i2 = 20;

string str = "str";

Class1 c = new Class1();

Add(i1);

AddWithRef(ref i2);

Add(c.i);

StringConvert(str);

StringConvert(c);

Console.WriteLine(i1);

Console.WriteLine(i2);

Console.WriteLine(c.i);

Console.WriteLine(str);

Console.WriteLine(c.str);

}

}

7.写出程序的输出结果

public abstract class A

{

public A()

{

Console.WriteLine('A');

}

public virtual void Fun()

{

Console.WriteLine("A.Fun()");

}

}

public class B: A

{

public B()

{

Console.WriteLine('B');

}

public new void Fun()

{

Console.WriteLine("B.Fun()");

}

public static void Main()

{

A a = new B();

a.Fun();

}

}

8. 写出程序的输出结果:

public class A

{

public virtual void Fun1(int i)

{

Console.WriteLine(i);

}

public void Fun2(A a)

{

a.Fun1(1);

Fun1(5);

}

}

public class B : A

{

public override void Fun1(int i)

{

base.Fun1 (i + 1);

}

public static void Main()

{

B b = new B();

A a = new A();

a.Fun2(b);

b.Fun2(a);

}

}

9. 一列数的规则如下: 112358132134......

求第30位数是多少,用递归算法实现。(C#语言)

-------------------------------------------

a0 = 0,a1 = 1,An = An-1 + An-2(n>=2)
int[] iArray = new int[31];
iArray[0] = 0;
iArray[1] = 1;

for (int i = 2; i <= 30; i++)
{
iArray[i] = iArray[i - 1] + iArray[i - 2];
}
---------------
参考答案二---------------------------------

int i=0,ii=1,s=1,num=0;
while(num<=30)
{
s=i+ii;
Response.Write(i+"+"+ii+"="+s+"
");
if(s==1)
{
i=1;
}
else
{
i=s-i;
}
ii=s;
num++;
}

========================

10.程序设计: 猫大叫一声,所有的老鼠都开始逃跑,主人被惊醒。(C#语言)

要求:1.要有联动性,老鼠和主人的行为是被动的。

2.考虑可扩展性,猫的叫声可能引起其他联动效应。

三个类,,老鼠和主人

public sealed class Cat

{

// 猫叫时引发的事件

public event EventHandler Calling;

public void Call()

{

Console.WrietLine("猫叫了...");

if(Calling != null) // 检查是否有事件注册

Calling(this, EventArgs.Empty); // 调用事件注册的方法。

}

}

// 老鼠,提供一个方法表示逃跑

public sealed calss Mouse

{

public void Escape(object sender, EventArgs e)

{

Console.WriteLine("老鼠逃跑了...");

}

}

// 主人,发生猫叫的时候惊醒

public sealed class Master

{

public void Wakened(object sender, EventArgs e)

{

Console.WriteLine("主人惊醒了...);

}

}

// 用于测试的执行方法

// 程序入口点

public static Program

{

public static int Main(string[] args)

{

// 建立猫

Cat cat = new Cat();

// 建立老鼠

Mouse mouse = new Mouse();

// 建立主人

Master master = new Master();

// 注册事件

cat.Calling += new EventHandler(mouse.Escape);

cat.Calling += new EventHandler(master.Wakened);

二、 选择题(每题2分 20 )

1、进行软件质量管理的重要性有:(ABCD)【中级】

A、维护降低成本 B、法律上的要求 C、市场竞争的需要

D、质量标准化的趋势 E、软件工程的需要 FCMM过程的一部分

G、方便与客户进一步沟通为后期的实施打好基础

2、以测试的形态分测试可以分为:(ABC)【中级】

A、建构性测试 B、系统测试 C、专项测试

D、单元测试 E、组件测试 F、集成测试

3、选出属于黑盒测试方法的选项(ABC)【初级】

A、测试用例覆盖 B、输入覆盖 C、输出覆盖

D、分支覆盖 E、语句覆盖 F、条件覆盖

4、编写测试计划的目的是:(ABC)【中级】

A、使测试工作顺利进行B、使项目参与人员沟通更舒畅C、使测试工作更加系统化

D、软件工程以及软件过程的需要 E、软件过程规范化的要求 F、控制软件质量

5、依存关系有4种分别是:(ABCD)【高级】

A、开始-结束 B、开始-开始 C、结束-开始

D、结束-结束 E、开始-实施-结束 F、结束-审核-开始

6、软件质量管理(QM)应有质量保证(QA)和质量控制(QC)组成,下面的选项属于QC得是:(ABC)【高级】

A、测试 B、跟踪 C、监督

D、制定计划 E、需求审查 F、程序代码审查

7、实施缺陷跟踪的目的是:(ABCD)【中级】

A、软件质量无法控制 B、问题无法量化 C、重复问题接连产生

D、解决问题的知识无法保留E、确保缺陷得到解决F、使问题形成完整的闭环处理

8、使用软件测试工具的目的:(ABC)【中级】

A、帮助测试寻找问题 B、协助问题的诊断 C、节省测试时间

D、提高Bug的发现率 E、更好的控制缺陷提高软件质量 F、更好的协助开发人员

9、典型的瀑布模型的四个阶段是:(ABCD)【高级】

A、分析 B、设计 C、编码

D、测试 E、需求调研 F、实施

10PSP是指个人软件过程 ,是一种可用于( A )、( B )和( C )个人软件工作方式的自我改善过程。【高级】

A、控制 B、管理 C、改进

D、高效 E、充分 F、适宜

三、 问答题

1、测试人员在软件开发过程中的任务是什么?(初级)(5分)

答:1、寻找Bug

2、避免软件开发过程中的缺陷;

3、衡量软件的品质;

4、关注用户的需求。

总的目标是:确保软件的质量。

2、在您以往的工作中,一条软件缺陷(或者叫Bug)记录都包含了哪些内容?如何提交高质量的软件缺陷(Bug)记录?(初级)(6分)

答:一条Bug记录最基本应包含:编号、Bug所属模块、Bug描述、Bug级别、发现日期、发现人、修改日期、修改人、修改方法、回归结果等等;要有效的发现Bug需参考需求以及详细设计等前期文档设计出高效的测试用例,然后严格执行测试用例,对发现的问题要充分确认肯定,然后再向外发布如此才能提高提交Bug的质量。

3、界面测试题及设计题。请找出下面界面中所存在的问题并分别列出;用黑盒测试的任何一种方法设计出此登陆窗体的测试用例。(中级)(6分)

答:1、窗体的标题栏中为空,没有给出标题。

2、用户名和密码控件的字体不一致并且没有对齐。

3、文本框的大小不一致没有对其。

4、确定和取消按钮控件的大小不一致。

4、黑盒测试和白盒测试是软件测试的两种基本方法,请分别说明各自的优点和缺点!(中级)(5分)

答:黑盒测试的优点有
1)比较简单,不需要了解程序内部的代码及实现;

2)与软件的内部实现无关;

3)从用户角度出发,能很容易的知道用户会用到哪些功能,会遇到哪些问题;

4)基于软件开发文档,所以也能知道软件实现了文档中的哪些功能;

5)在做软件自动化测试时较为方便。

黑盒测试的缺点有:
1)不可能覆盖所有的代码,覆盖率较低,大概只能达到总代码量的30%

2)自动化测试的复用性较低。

白盒测试的优点有:

帮助软件测试人员增大代码的覆盖率,提高代码的质量,发现代码中隐藏的问题。

白盒测试的缺点有:

1)程序运行会有很多不同的路径,不可能测试所有的运行路径;

2)测试基于代码,只能测试开发人员做的对不对,而不能知道设计的正确与否,可能会漏掉一些功能需求;

3)系统庞大时,测试开销会非常大。

5、根据自己的理解回答什么是软件测试,软件测试分为哪几个阶段。(初级)(5分)

答:软件测试是一个为了寻找软件中的错误而运行软件的过程,一个成功的测试是指找到了迄今为止尚未发现的错误的测试。

软件测试一般分为单元测试、集成测试和系统测试。

6、根据自己的理解什么是测试用例和测试规程,设计一个测试用例应当从哪几方面考虑?(中级)(10分)

答:狭义的讲,一个测试用例就是测试人员用以测试被测软件的某个特性或特性组合的一组数据。这组数据可能是从用户处得来的实际的一组数据,也可能是测试人员专门设计出来的测试软件某些功能的一组数据。

测试规程就是详细的对测试用例设计方法、测试方法、测试工具、测试环境和测试数据进行描述的文档,还可以包括能把某个或某一组测试用例应用到被测软件上完成某项测试的一系列的操作步骤。

设计测试用例应当从以下几方面考虑:边界值,等价类划分,有效/无效值等。

7、 什么是软件质量保证?软件质量保证人员与开发人员的关系如何?(高级) (10分)

答:软件质量保证就是通过确保软件过程的质量,来保证软件产品的质量。

软件质量保证人员和开发人员之间具有管理上的严格的独立性,两个小组的管理员都不能越权管理另一组,但都可以向更高层的管理者汇报软件开发中的问题

四、 设计题

1).输入三个整数,判断三个整数能否构成一个三角形,请用黑盒测试方法中的一种设计出相应的测试用例并详细说明所使用的黑盒测试方法。(中高级)(15分)

相关内容

热门阅读
随机推荐