1. 程式人生 > >【C#】筆試知識點

【C#】筆試知識點

C#筆試知識點

1.String與Stringbuilder的區別:
String自動分配記憶體大小,每次往裡面寫新東西,就會重新分配一段記憶體,然後把地址指向新的這塊空間,是由C#記憶體管理自動管理的。
Stringbuilder會事先分配好一段空間,append的時候,是操作的同一塊空間,如果新串超過原本大小,記憶體空間自動加倍。

2.C#如何呼叫c++靜態庫(lib):
可以用CLR(新)或者Managed c++(老)將lib封裝成managed dll供C#直接呼叫。
將lib封裝成native dll,C#中通過DllImport呼叫dll。
將lib封裝成native dll, 再用CLR封裝native dll成managed dll供C#直接呼叫。
將lib封裝為COM,在C#中呼叫COM。

3.長度為100的字串,從abcdefgh中隨機抽取100個字元組成:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace csharpconsole
{
    class Program
    {
        static void Main(string[] args)
        {
            StringBuilder strOut = new StringBuilder(0
, 100); String strSrc = "a, b, c, d, e, f, g, h"; String[] strDes = strSrc.Split(','); int len = strDes.Length; Random rd = new Random(); int i = 0; for (; i < 100; i++) { StrOut = strDes[rd.Next(len)]; } Console.ReadKey(); } } }

4.產生一個int陣列,長度為100,並向其中隨機插入1-100,並且不能重複:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace csharpconsole
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] intArr = new int[100];
            ArrayList myList = new ArrayList();
            Random rd = new Random();
            int num = 0; /* 1-100產生隨機數 */
            int i = 0;

            /* 生成100個不重複的1-100的數 */
            while (myList.Count < 100)
            {
                num = rd.Next(1, 101);
                if (!myList.Contains(num))
                {
                    myList.Add(num);
                }
            }

            for (; i < 100; i++)
            {
                intArr[i] = (int)myList[i];
            }

            foreach (int a in intArr)
            {
                Console.WriteLine(a);
            }

            Console.ReadKey();
        }
    }
}

5.把一個Array複製到ArrayList裡:

foreach (object o in array)
{ 
    arrayList.Add(o);
}

6.寫一個函式計算當引數為N的值:1-2+3-4+5-6+7……+N:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace csharpconsole
{
    class Program
    {
        static void Main(string[] args)
        {
            int num = 0;
            String str = "";
            int sum = 0;

            Console.WriteLine("請輸入一個100以內的數:");
            str = Console.ReadLine();

            num = int.Parse(str);

            for (int i = 1; i <= num; i++)
            {
                sum += ((int)Math.Pow(-1, i + 1)) * i;
            }

            Console.WriteLine(sum);

            Console.ReadKey();
        }
    }
}

7.斐波拉契數列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34……:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace csharpconsole
{
    class Program
    {
        static int MyALG(int num)
        {
            if (num <= 0)
            {
                return 0;
            }
            else if ((1 == num) || (2 == num))
            {
                return 1;
            }
            else
            {
                return (MyALG(num - 1) + MyALG(num - 2));
            }
        }

        static void Main(string[] args)
        {
            int result = 0;
            result = MyALG(30);

            Console.WriteLine(result.ToString());
            Console.ReadKey();
        }
    }
}

9.虛方法(virtual)和抽象類(abstract)的區別和聯絡:
(1)、抽象方法只有宣告沒有實現程式碼,需要在子類中實現;虛擬方法有宣告和實現程式碼,並且可以在子類中重寫,也可以不重寫使用父類的預設實現。
(2)、抽象類不能被例項化(不可以new),只能例項化實現了全部抽象方法的派生類;而包含虛方法的類可以例項化。
(3)、虛方法與多型性關係密切,虛方法允許派生類完全或部分重寫該類的方法,需寫方法體。抽象方法只是一個定義,沒有方法體,也就是沒有{},也不要在裡面寫內容。
(4)、抽象方法是虛擬方法兩個相像的一點是都用override重寫。

10.值型別和引用型別的區別:
值型別:儲存在堆疊中。bool, byte, chat, decimal, double, enum, float, int, long, sbyte, short, strut, uint, ulong, ushort。
引用型別:儲存在託管堆中。class, delegate, interface, object, string。引用型別包含一個指標,指向堆中儲存物件本身的位置。因為引用型別只包含引用,不包含實際的值,對方法體內參數所做的任何修改都將影響傳遞給方法呼叫的引用型別的變數。
託管程式碼:基於CLR的語言編譯器開發的程式碼稱為託管程式碼。
託管堆:是CLR中自動記憶體管理的基礎。初始化新程序時,執行時會為程序保留一個連續的地址空間區域。這個保留的地址空間被稱為託管堆。託管堆維護著一個指標,用它指向將在堆中分配的下一個物件的地址。最初,該指標設定為指向託管堆的基址。
由於對物件的引用會在程式執行過程中被傳遞,所以引用型別不能夠被使用者方便的釋放,.NET的垃圾收集處理機制,會在引用為0的時候,自動釋放掉引用型別變數。

11.結構和類的區別:
結構是值型別,類是引用型別;結構不能有建構函式和解構函式;類可以同時有建構函式和解構函式;結構不支援繼承,而類支援繼承。

12.委託(delegate)和事件(event):
委託:委託是型別安全,面向物件的函式指標的實現,並且在許多一個元件需要回調到使用它的元件這樣的情況下使用。
事件:事件是使一個類或物件能夠提供通知的成員。事件宣告像域宣告一樣,除了宣告包含event關鍵字並且型別必須為委託型別。

13.物件型別(object)和動態型別(dynamic)的區別:
物件型別:是所有資料型別的終極基類。Object是System.Object類的別名。當一個值型別轉換為物件型別時,則被稱為裝箱;另一方面,當一個物件型別轉換為值型別時,則被稱為 拆箱。
動態型別:可以儲存任何型別的值在動態資料型別變數中。這些變數的型別檢查是在執行時發生的。
動態型別與物件型別相似,但是物件型別變數的型別檢查是在編譯時發生的,而動態型別變數的型別檢查是在執行時發生的。

14.傳入引數:
包括值引數,引用引數,輸出引數和引數陣列。
引用引數(ref關鍵字):實參在呼叫前需要初始化,並且值可以被傳入和傳出;
輸出引數(out關鍵字):實參在呼叫前不必初始化,在方法中必須要初始化,值只能傳出不能傳入。

15.C#與C的區別:
C#不支援#include語句。它只用using語句。
C#中,類定義在最後不使用分號。
C#不支援多重繼承。
資料型別的顯示轉換在C#中比C中安全很多。
C#中switch也可用於字串值。
命令列引數陣列(params,即可變引數)的行為在C#中和C中不一樣。

16.介面和類的區別:
(1)、介面類似於類,但介面的成員都沒有執行方式,它只是方法、屬性、事件和索引符的組合而已,並且也只能包含這四種成員;類除了這四種成員之外還可以別的成員(如欄位)。
(2)、不能例項化一個介面,介面只包括成員的簽名;而類可以例項化(abstract類除外)。
(3)、介面沒有建構函式,類有建構函式。
(4)、介面不能進行運算子的過載,類可以進行運算子過載。
(5)、介面的成員沒有任何修飾符,其成員總是公共的,而類的成員則可以有修飾符(如:虛擬或者靜態)。
(6)、派生於介面的類必須實現介面中所有成員的執行方式,而從類派生則不然。

17.const和readonly區別:
readonly修飾的欄位,其初始化僅是固定了其引用(地址不能修改),但它引用的物件的屬性是可以更改的。
const宣告的欄位不能使用static修飾符,而readonly可以使用static修飾符。
const欄位只能在宣告時初始化,而readonly可以在宣告時或在建構函式中初始化。
const欄位的值在在編譯階段就計算出來了,而readonly的值在執行時計算。

18.異常(try、catch、finally、throw):
try:可能丟擲異常的程式碼;
catch:出現異常後針對的處理辦法;
finally:不論是否出現異常都執行的程式碼(通常是一些釋放資源的程式碼),finally塊是可以省略的。
一個try塊可以對應多個catch塊,其中按丟擲的異常類尋找對應的catch塊,也可能找不到,如果一直沒有找到就會終止程式,返回一條錯誤程式碼。
異常處理可以互相巢狀,在內層找不到對應的處理程式碼,會向外層找。

(1)、try、catch、finally例子:

/* 
結果:
finally1
試圖除以0.
finally2
*/
static void Main(string[] args)
{
    int n1 = 10;
    int n2 = 0;
    int result;

    /* 由於除數為0,丟擲異常,內層找不到會找外層的異常catch處理 */
    try
    {
        /* try catch的巢狀 */
        try
        {
            result = n1 / n2;
            Console.WriteLine("{0}", result);
        }
        catch (MemberAccessException e)
        {
            Console.WriteLine(e.Message);
        }
        finally
        {
            Console.WriteLine("finally1");
        }
    }
    /* 2個外層catch */
    catch (DivideByZeroException e)
    {
        /* 最後找到是由此catch處理 */
        Console.WriteLine(e.Message);
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
    finally
    {
        Console.WriteLine("finally2");
    }

    Console.ReadKey();
}

(2)、自定義異常throw例子:

/*
結果:
除數為0
*/
/* 自定義異常必須繼承於ApplicationException類 */
private class TestException : ApplicationException
{
    public string msg;
    public TestException(string msg)
    {
        this.msg = msg;
    }
}

/* 定義方法和異常丟擲程式碼 */
static double mul(double n1, double n2)
{
    if (n2 == 0.0)
    {
        /* 除數為0就丟擲異常 */
        throw new TestException("除數為0");
    }

    return n1 / n2;
}

static void Main(string[] args)
{
    double n1 = 10.0;
    double n2 = 0.0;
    double result;
    try
    {
        /* double除法預設除數為0會返回一個很大的值 */
        result = mul(n1, n2);
        Console.WriteLine(result);
    }
    catch (TestException e)
    {
        Console.WriteLine(e.msg);
    }
    Console.ReadKey();
}

19.特性(Attribute)和反射(Reflection):
特性為類、方法、結構、列舉、元件等新增自定義的屬性(元資料),反射可以獲取這些屬性,需要的時候通過反射提取出來使用。

20.屬性(Property)和索引器(Indexer):
屬性要通過一個叫做訪問器(accessor)的東東,對私有成員變數進行安全帶驗證的訪問方式。即get、set屬性。
索引器是可以通過方便的方式訪問物件(例項化的類)中的成員陣列或集合。(注意這裡是陣列或集合)

21.執行緒:
System.Threading名字空間。
Start():啟動執行緒;
Sleep(int):靜態方法,暫停當前執行緒指定的毫秒數;
Abort():通常使用該方法來終止一個執行緒;
Suspend():該方法並不終止未完成的執行緒,它僅僅掛起執行緒,以後還可恢復;
Resume():恢復被Suspend()方法掛起的執行緒的執行。

(1)、執行緒使用:

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread t1 = new Thread(new ThreadStart(TestMethod));
            Thread t2 = new Thread(new ParameterizedThreadStart(TestMethod));
            t1.IsBackground = true; //設定當前子執行緒為後臺執行緒,為後臺執行緒意味著,主執行緒關閉後,其他子執行緒都同時關閉
            t2.IsBackground = true;
            t1.Start();
            t2.Start("hello");
            Console.ReadKey();
        }

        public static void TestMethod()
        {
            Console.WriteLine("不帶引數的執行緒函式");
        }

        public static void TestMethod(object data)
        {
            string datastr = data as string;
            Console.WriteLine("帶引數的執行緒函式,引數為:{0}", datastr);
        }
    } 
}

(2)、執行緒池:

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            //將工作項加入到執行緒池佇列中,這裡可以傳遞一個執行緒引數
            ThreadPool.QueueUserWorkItem(TestMethod, "Hello");
            Console.ReadKey();
        }

        public static void TestMethod(object data)
        {
            string datastr = data as string;
            Console.WriteLine(datastr);
        }
    }
}

(3)、Lock互斥鎖:
就是多執行緒訪問臨界區程式碼,一次只能讓一個執行緒呼叫,以保護全域性變數。這裡要注意,lock只能鎖定一個引用型別變數,即一個地址。

22.task/taskfactory:
後面補充,暫時用不到這麼深入的技術。

23.Parallel:
後面補充,暫時用不到這麼深入的技術。

24.有空的時候研究一下CLR、元資料、IL。