C#基礎知識面試經典[整理]

来源:http://www.cnblogs.com/51pansou/archive/2016/03/16/5283772.html
-Advertisement-
Play Games

當初學 C# 時是找個人大概問了一下數據類型和分支語句就開始做項目了。這兩天又全面的看了一下相關的基礎知識(學而時習之嘛),總結了25個問題: 1.靜態成員和非靜態成員的區別? 2.const 和 static readonly 區別? 3.extern 是什麼意思? 4.abstract 是什麼...


個人網站:http://www.51pansou.com

.net視頻下載:.net視頻教程

.net源碼下載:.net源碼

    當初學 C# 時是找個人大概問了一下數據類型和分支語句就開始做項目了。這兩天又全面的看了一下相關的基礎知識(學而時習之嘛),總結了25個問題:

1.靜態成員和非靜態成員的區別?
2.const 和 static readonly 區別?
3.extern 是什麼意思?
4.abstract 是什麼意思?
5.internal 修飾符起什麼作用?
6.sealed 修飾符是乾什麼的?
7.override 和 overload 的區別?
8.什麼是索引指示器?
9.new 修飾符是起什麼作用?
10.this 關鍵字的含義?
11.可以使用抽象函數重寫基類中的虛函數嗎?
12.密封類可以有虛函數嗎?
13.什麼是屬性訪問器?
14.abstract 可以和 virtual 一起使用嗎?可以和 override 一起使用嗎?
15.介面可以包含哪些成員?
16.類和結構的區別?
17.介面的多繼承會帶來哪些問題?
18.抽象類和介面的區別?
19.別名指示符是什麼?
20.如何手工釋放資源?
21.P/Invoke是什麼?
22.StringBuilder 和 String 的區別?
23.explicit 和 implicit 的含義?
24.params 有什麼用?
25.什麼是反射?

以下是我做的一份參考答案(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 修飾符,表示抽象重寫了基類中該函數的實現

示例:

 &nb

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 效果: 編寫節目類 屬性:播出時間、時段、名稱、視頻路徑 編寫頻道基類 屬性:頻道名稱、頻道節目單位置、節目列表 抽象方法:Fetch() 編寫頻道子類 繼承“頻道基類”,實現Fetch()【只寫方法聲明】 編寫頻道工廠類 方法:實現創建頻道子類 第一步.創建幾個類: 01:創建一個電視類(TvPr
  • 在進行 .NET Web MVC 框架開發的網站程式的時候,我們都會遇到最關鍵的問題,數據傳輸。 .NET MVC 4中的ControllerBase類建議我們用ViewBag動態數據字典形式(type:dynamic,JavaScript就是動態語言,只在運行時候才進行類型判斷,而不是在編譯),或
  • 這學期學了Web技術這門課,但對這門課是做什麼的、有什麼用處並不瞭解,教材是Asp.net實用網站開發,對我這樣的初學者大概是深了一點,所以決定對Web技術的背景知識做下整理。 1.Web工作原理 Web全稱為World Wide Web(WWW)。簡單地說,Web是網際網路提供的一種服務,通過它可以
  • 委托是一種類型,它封裝了一類方法,這些方法具有相同的方法簽名(signature)。定義聽起來有點拗口,首先可以確定委托是一種數據類型,那麼什麼是方法簽名,其實就是指方法的輸入參數列表和輸出參數類型。來看下麵的例子,類deleMthod定義了3個方法,add、minus和multi,他們都具有相同的
  • 一、jQuery是什麼 1.jQuery是一套JavaScript腳本庫,而不是框架;就好比“System是程式集”是類庫,而“ASP.NET MVC”是框架; 2.jQuery並不能幫助我們解決腳本引用管理和功能管理,這些都是框架要做的事; 3.腳本庫能幫助我們完成編碼邏輯,實現業務功能 二、jQ...
  • 如果你的項目要提供多個dll給別人用,那麼不妨讓你的dll合併為一個,讓別人看起來簡潔,引用起來不會過於繁瑣。 本篇比較少,但也算是比較實用吧。 Imerge下載地址:https://www.microsoft.com/en-us/download/details.aspx?id=17630 下載完
  • 上一篇我們快速的搭建了一個小案例,但是並沒有對其中的方法進行介紹,這一篇我來逐一解析下。 一:從override的那些方法說起 不管怎麼樣,我們先上代碼,如下: 首先我們知道的一個現象就是,所有的持久連接類都是繼承於PersistentConnection,那麼感興趣的問題就來了,Persisten
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...