.NET基础知识问题汇总(持续更新中)

1. 简述 private、 protected、 public、internal修饰符的访问权限。

private: 只能在类的内部访问,即使子类也不能够访问

protected: 可以在类的内部访问,子类也可以访问,但无法通过外部访问。

public: 可以在类或子类的内部访问,也可以通过外部访问。

internal: 只能在程序集内部访问。


2. 列举ASP.NET 页面之间传递值的几种方式,并简单描述各自的优缺点。

QueryString, Session, Application, Cookie, Transfer.

QueryString: 存放于URL中,优点是使用方便,占用服务器资源少,缺点是安全性较差(暴露在了URL中),而且只能传递值,不能传递对象;

Session: 数据存放于服务器端,是用户级的全局资源,优点是使用方便,并且可以进行对象传递, 缺点是消耗服务器资源较大,容易丢失(在数据量比较大的情况下);

Application: 应用程序级全局变量,占用服务资源少,但因为是全局变量,所以应该尽量避免用户级的更改。

Cookie: 存放于客户端,依赖客户端,在客户端禁止Cookie的情况下则无法使用,此外,Cookie存在被盗窃的风险。

Transfer: ?


3. 一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30位数是多少, 用递归算法实现

  public class FibonacciSequence
    {
        public static int GetValueFromIndex(int index)
        {
            if (index < 0) throw new ArgumentOutOfRangeException("Index");

            if (index == 0) return 0;

            return index == 1 ? 1 : (GetValueFromIndex(index - 1) + GetValueFromIndex(index - 2));
        }
    }

4.  C#中的委托是什么?事件是不是一种委托?

事件是一种特殊的委托,但它delegate要多了一些限制。


5. 请说出override与overload的区别,并举例说明

这个问题可能需要从3个方面来讲:重载函数,覆盖函数与普通函数。

先看下面的代码:

namespace ConsoleApplication
{
    class TestClass
    { 
        public void MethodToOverload()
        {
            Console.WriteLine(String.Format("Class: {0}, Signature: {1}", "TestClass", "void MethodToOverload()"));
        }

        public void MethodToOverload(String para)
        {
            Console.WriteLine(String.Format("Class: {0}, Signature: {1}", "TestClass", "void MethodToOverload(String para)"));
        }

        public virtual void MethodToOverride()
        {
            Console.WriteLine(String.Format("Class: {0}, Signature: {1}", "TestClass", "void MethodToOerride()"));
        }

        public void NormalMethod()
        {
            Console.WriteLine(String.Format("Class: {0}, Signature: {1}", "TestClass", "void NormalMethod()"));
        }
    }

    class TestInheritClass : TestClass
    {
        public override void MethodToOverride()
        {
            Console.WriteLine(String.Format("Class: {0}, Signature: {1}", "TestInheritClass", "void MethodToOerride()"));
        }

        public void NormalMethod()
        {
            Console.WriteLine(String.Format("Class: {0}, Signature: {1}", "TestInheritClass", "void NormalMethod()"));
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            TestClass inheritClass = new TestInheritClass();

            inheritClass.MethodToOverride();

            inheritClass.NormalMethod();

            ((TestInheritClass)inheritClass).NormalMethod();

            inheritClass.MethodToOverload();

            inheritClass.MethodToOverload("para");
        }
    }
}
运行结果如下:

Class: TestInheritClass, Signature: void MethodToOerride()
Class: TestClass, Signature: void NormalMethod()
Class: TestInheritClass, Signature: void NormalMethod()
Class: TestClass, Signature: void MethodToOverload()
Class: TestClass, Signature: void MethodToOverload(String para)

第一个是被override的函数,我已经将继承类转换成了基类,但是,被override的函数依然调用的是继承类的成员函数,这是覆盖函数的特性。其关键是两个单词:virtual和override;所以,virtual函数是可以被派生类覆盖的(abstract也可以)。

第二个是普通的函数,我在派生类中又进行了重新定义,由于我已经将派生类的实例转换成了基类,所以,调用时,显示出来的是基类的特性。再将它转换成派生类,调用时有调用了派生类的函数,显然,这里没有看到覆盖这一特性。

第三个是重载函数,与覆盖函数不同的是,重载函数的依据是函数签名(除返回值),对于相同的函数名,根据参数的类型或数量来决定调用哪个函数。


6. 描述一下C#中索引器的实现过程,是否只能根据数字进行索引?

索引可以使用对象,详见示例代码:

namespace ConsoleApplication
{
    public class IndexClass
    {
        public string this[int index]
        {
            get{
                return String.Format("{0}th element", index);
            }
        }

        public string this[string key]
        {
            get
            {
                return String.Format("element with key = {0}", key);
            }
        }
    }
}

7.请指出下面代码中可能出现的编译错误

namespace PlayAround
{
    class Program
    {
        static void Main(string[] args)
        {
            int ival = 1024;

            {
                double ival = 3.14; // error 1
                string str = "hello";
            }

            {
                double str = 3.1415926;
            }

            string str = "world"; // error 2
        }
    }
}

两个编译错误的原因都是因为本地区块的声明与顶层的声明冲突,与声明的先后顺序无关。


8.下列选项中,哪些选项会导致编译失败

namespace PlayAround
{
    internal class SampleClass
    {
    }


    class Program
    {
        public const SampleClass objA = new SampleClass(); // option A
        public const int iB = 0; // option B
        public readonly SampleClass objC = new SampleClass(); // option C
        public static SampleClass objD = new SampleClass(); // option D
        public const SampleClass objE = null; // option E


        static void Main(string[] args)
        {


        }
    }
}

经测试发现,只有option A会导致编译失败,因为const在编译期间值就需要确定了,而new操作需要在堆上申请内存,两者存在时间上的冲突,注定无法共存。


9.下列程序会输出什么结果,并分析原因。

namespace ConsoleApplication
{
    class Program
    {
        static IEnumerable<int> WithNoYield()
        {
            IList<int> list = new List<int>();

            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine(i.ToString());

                if (i > 2) list.Add(i);
            }

            return list;
        }


        static IEnumerable<int> WithYield()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine(String.Format("Yield: {0}", i));

                if (i > 2) yield return i;
            }
        }

        static void Print(IEnumerable<int> list)
        {
            foreach (int i in list)
            {
                Console.WriteLine(i.ToString());
            }
        }

        static void Main(string[] args)
        {
            var list1 = WithNoYield();

            var list2 = WithYield();

            Console.WriteLine("list1: ");
            Print(list1);
            Console.WriteLine("list2: ");
            Print(list2);
        }
    }

输出结果:

0
1
2
3
4
list1:
3
4
list2:
Yield: 0
Yield: 1
Yield: 2
Yield: 3
3
Yield: 4
4

从结果中,可以发现,yield的计算并不是在返回时执行,而是在进行遍历的时候执行,这是一种延迟计算的概念。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值