主頁 > .NET開發 > C#泛型學習筆記

C#泛型學習筆記

2020-09-20 09:33:33 .NET開發

   本筆記摘抄自:https://www.cnblogs.com/dotnet261010/p/9034594.html,記錄一下學習程序以備后續查用,

    一、什么是泛型

    泛型是C#2.0推出的新語法,不是語法糖,而是2.0由框架升級提供的功能,泛型類就類似于一個模板,可以在需要時為這個模板傳入任何我們需要的型別,

    二、為什么使用泛型

    下面代碼演示輸出幾種型別的相關資訊:

    class Program
    {
        /// <summary>
        /// 列印幫助類
        /// </summary>
        public class ShowHelper
        {
            /// <summary>
            /// ShowInt
            /// </summary>
            /// <param name="intParam"></param>
            public static void ShowInt(int intParam)
            {
                Console.WriteLine($"Class={typeof(ShowHelper).Name},Type={intParam.GetType().Name},Parameter={intParam}");
            }

            /// <summary>
            /// ShowString
            /// </summary>
            /// <param name="strParam"></param>
            public static void ShowString(string strParam)
            {
                Console.WriteLine($"Class={typeof(ShowHelper).Name},Type={strParam.GetType().Name},Parameter={strParam}");
            }

            /// <summary>
            /// ShowDateTime
            /// </summary>
            /// <param name="dtParam"></param>
            public static void ShowDateTime(DateTime dtParam)
            {
                Console.WriteLine($"Class={typeof(ShowHelper).Name},Type={dtParam.GetType().Name},Parameter={dtParam}");
            }
        }

        static void Main(string[] args)
        {
            #region 非泛型列印方式一
            ShowHelper.ShowInt(123);
            ShowHelper.ShowString("Hello World.");
            ShowHelper.ShowDateTime(DateTime.Now);
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    上面3個方法很相似,除了引數型別不同外,實作的功能是一樣的,可以稍作優化,

    下面代碼演示使用繼承的方式輸出幾種型別的相關資訊:

    class Program
    {
        /// <summary>
        /// 列印幫助類
        /// </summary>
        public class ShowHelper
        {
            /// <summary>
            /// ShowType
            /// </summary>
            /// <param name="obj"></param>
            public static void ShowType(object obj)
            {
                Console.WriteLine($"Class={typeof(ShowHelper).Name},Type={obj.GetType().Name},Parameter={obj}");
            }
        }

        static void Main(string[] args)
        {
            #region 非泛型列印方式二
            ShowHelper.ShowType(123);
            ShowHelper.ShowType("Hello World.");
            ShowHelper.ShowType(DateTime.Now);
            Console.Read();
            #endregion
        }
    }
View Code

    功能實作沒有問題,只是object與其它型別的轉換,涉及到裝箱和拆箱的程序,這個是會損耗程式的性能的,

    三、泛型型別引數

    在泛型型別或方法的定義中,泛型型別引數可認為是特定型別的占位符,

    下面代碼演示使用泛型的方式輸出幾種型別的相關資訊:

    class Program
    {
        /// <summary>
        /// 列印幫助類
        /// </summary>
        public class ShowHelper
        {
            /// <summary>
            /// Show
            /// </summary>
            /// <param name="obj"></param>
            public static void Show<T>(T tParam)
            {
                Console.WriteLine($"Class={typeof(ShowHelper).Name},Type={tParam.GetType().Name},Parameter={tParam}");
            }
        }

        static void Main(string[] args)
        {
            #region 泛型列印方式
            ShowHelper.Show(123);
            ShowHelper.Show("Hello World.");
            ShowHelper.Show(DateTime.Now);
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    1、為什么泛型可以解決上面的問題呢?

    泛型是延遲宣告的:即定義的時候沒有指定具體的引數型別,把引數型別的宣告推遲到呼叫的時候才給它指定, 

    2、泛型究竟是如何作業的呢?

    程式執行原理:控制臺程式最侄訓編譯成一個exe程式,當exe被點擊的時候,會經過JIT(即時編譯器)的編譯,最終生成二進制代碼才能被計算機執行,

    泛型作業原理:泛型加入到語法以后,VS自帶的編譯器做了升級,升級之后編譯時若遇到泛型,會做特殊的處理:生成占位符,然后經過JIT編譯的時候,

會把上面編譯生成的占位符替換成具體的資料型別,

    下面代碼演示泛型占位符:

    class Program
    {
        static void Main(string[] args)
        {
            #region 泛型占位符
            Console.WriteLine(typeof(List<>));
            Console.WriteLine(typeof(Dictionary<,>));
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    3、泛型性能問題

    下面代碼演示泛型性能測驗:

    class Program
    {
        static void Main(string[] args)
        {
            #region 泛型性能測驗
            long commonTime = 0;
            long objectTime = 0;
            long genericTime = 0;
            Stopwatch watch = new Stopwatch();
            watch.Start();
            for (int i = 0; i < 10000; i++)
            {
                ShowHelper.ShowInt(123);
            }
            watch.Stop();
            commonTime = watch.ElapsedMilliseconds;

            watch.Reset();
            watch.Start();
            for (int i = 0; i < 10000; i++)
            {
                ShowHelper.ShowType(123);
            }
            watch.Stop();
            objectTime = watch.ElapsedMilliseconds;

            watch.Reset();
            watch.Start();
            for (int i = 0; i < 10000; i++)
            {
                ShowHelper.Show(123);
            }
            watch.Stop();
            genericTime = watch.ElapsedMilliseconds;

            Console.Clear();
            Console.WriteLine($"Common time={commonTime}ms");
            Console.WriteLine($"Object time={objectTime}ms");
            Console.WriteLine($"Generic time={genericTime}ms");
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    從結果可以看出,泛型的性能是最高的,

    四、泛型類

    下面代碼演示泛型類:

    class Program
    {
        /// <summary>
        /// 泛型類
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class GenericClass<T>
        {
            public T varT;
        }

        static void Main(string[] args)
        {
            #region 泛型類
            //T是int型別
            GenericClass<int> genericInt = new GenericClass<int>
            {
                varT = 123
            };
            Console.WriteLine($"The value of T={genericInt.varT}");
            //T是string型別
            GenericClass<string> genericString = new GenericClass<string>
            {
                varT = "123"
            };
            Console.WriteLine($"The value of T={genericString.varT}");
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    五、泛型介面

    注:泛型在宣告的時候可以不指定具體的型別,繼承的時候也可以不指定具體型別,但是在使用的時候必須指定具體型別,

    下面代碼演示泛型介面:

    class Program
    {
        /// <summary>
        /// 泛型介面
        /// </summary>
        public interface IGenericInterface<T>
        {
            T GetT(T t);
        }

        /// <summary>
        /// 泛型介面實作類
        /// </summary>
        /// <param name="args"></param>
        public class GenericGet<T> : IGenericInterface<T>
        {
            T varT;
            public T GetT(T t)
            {
                varT = t;
                return varT;
            }
        }

        static void Main(string[] args)
        {
            #region 泛型介面
            IGenericInterface<int> genericInterface = new GenericGet<int>();
            var result = genericInterface.GetT(123);
            Console.WriteLine($"Result={result}");
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    六、泛型委托

    下面代碼演示泛型委托:

    class Program
    {
        /// <summary>
        /// 泛型委托
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        public delegate void SayHi<T>(T t);

        static void Main(string[] args)
        {
            #region 泛型委托
            SayHi<string> sayHi = SayHello;
            sayHi("Hello World");
            Console.Read();
            #endregion
        }

        /// <summary>
        /// SayHello
        /// </summary>
        /// <param name="greeting"></param>
        public static void SayHello(string greeting)
        {
            Console.WriteLine($"{greeting}");
        }
    }
View Code

    運行結果如下:

    七、泛型約束

    泛型約束,實際上就是約束的型別T,使T必須遵循一定的規則,比如T必須繼承自某個類或者T必須實作某個介面等等,

    怎樣給泛型指定約束?其實也很簡單,只需要where關鍵字,加上約束的條件,

    泛型約束總共有五種:

約束 s說明
T:結構 型別引數必須是值型別
T:類 型別引數必須是參考型別;這一點也適用于任何類、介面、委托或陣列型別,
T:new() 型別引數必須具有無引數的公共建構式, 當與其他約束一起使用時,new() 約束必須最后指定,
T:<基類名> 型別引數必須是指定的基類或派生自指定的基類,
T:<介面名稱> 型別引數必須是指定的介面或實作指定的介面, 可以指定多個介面約束, 約束介面也可以是泛型的,

    7.1基類約束

    下面代碼演示基類約束:

        /// <summary>
        /// 運動類介面
        /// </summary>
        public interface ISports
        {
            void Pingpong();
        }

        /// <summary>
        /// 人類基類
        /// </summary>
        public class People
        {
            public string Name { get; set; }

            public virtual void Greeting()
            {
                Console.WriteLine("Hello World.");
            }
        }

        /// <summary>
        /// 中國人
        /// </summary>
        public class Chinese : People, ISports
        {
            public void FineTradition()
            {
                Console.WriteLine("自古以來,中華民族就保持著勤勞的優良傳統,");
            }
            public override void Greeting()
            {
                Console.WriteLine("吃飯了沒?");
            }

            public void Pingpong()
            {
                Console.WriteLine("乒乓球是中國的國球,");
            }
        }

        static void Main(string[] args)
        {
            #region 泛型約束:基類約束
            Chinese chinese = new Chinese()
            {
                Name = "中國人"
            };
            ShowPeople(chinese);
            Console.Read();
            #endregion
        }

        /// <summary>
        /// 基類約束
        /// </summary>
        /// <param name="obj"></param>
        public static void ShowPeople<T>(T tParam) where T:People
        {
            Console.WriteLine($"{((People)tParam).Name}");
        }
    }
View Code

    運行結果如下:

    注:基類約束時,基類不能是密封類,即不能是sealed類,sealed類表示該類不能被繼承,在這里用作約束就無任何意義了,因為sealed類沒有子類,

    7.2介面約束

    下面代碼演示介面約束:

    class Program
    {
        /// <summary>
        /// 運動類介面
        /// </summary>
        public interface ISports
        {
            void Pingpong();
        }

        /// <summary>
        /// 人類基類
        /// </summary>
        public class People
        {
            public string Name { get; set; }

            public virtual void Greeting()
            {
                Console.WriteLine("Hello World.");
            }
        }

        /// <summary>
        /// 中國人
        /// </summary>
        public class Chinese : People, ISports
        {
            public void FineTradition()
            {
                Console.WriteLine("自古以來,中華民族就保持著勤勞的優良傳統,");
            }
            public override void Greeting()
            {
                Console.WriteLine("吃飯了沒?");
            }

            public void Pingpong()
            {
                Console.WriteLine("乒乓球是中國的國球,");
            }
        }

        static void Main(string[] args)
        {
            #region 泛型約束:介面約束
            Chinese chinese = new Chinese()
            {
                Name = "中國人"
            };
            GetSportsByInterface(chinese);
            Console.Read();
            #endregion
        }

        /// <summary>
        /// 介面約束
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static T GetSportsByInterface<T>(T t) where T : ISports
        {
            t.Pingpong();
            return t;
        }
    }
View Code

    運行結果如下:

    7.3參考型別約束 class

    參考型別約束保證T一定是參考型別的,

    下面代碼演示參考型別約束:

    class Program
    {
        /// <summary>
        /// 運動類介面
        /// </summary>
        public interface ISports
        {
            void Pingpong();
        }

        /// <summary>
        /// 人類基類
        /// </summary>
        public class People
        {
            public string Name { get; set; }

            public virtual void Greeting()
            {
                Console.WriteLine("Hello World.");
            }
        }

        /// <summary>
        /// 中國人
        /// </summary>
        public class Chinese : People, ISports
        {
            public void FineTradition()
            {
                Console.WriteLine("自古以來,中華民族就保持著勤勞的優良傳統,");
            }
            public override void Greeting()
            {
                Console.WriteLine("吃飯了沒?");
            }

            public void Pingpong()
            {
                Console.WriteLine("乒乓球是中國的國球,");
            }
        }

        static void Main(string[] args)
        {
            #region 泛型約束:參考型別約束
            Chinese chinese = new Chinese()
            {
                Name = "中國人"
            };
            GetSportsByClass(chinese);
            Console.Read();
            #endregion
        }

        /// <summary>
        /// 參考型別約束
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static T GetSportsByClass<T>(T t) where T : class
        {
            if (t is ISports)
            {
                (t as ISports).Pingpong();
            }
            return t;
        }
    }
View Code

    運行結果如下:

    7.4值型別約束 struct

    值型別約束保證T一定是值型別的,

    下面代碼演示值型別約束:

    class Program
    {
        /// <summary>
        /// 績效工資
        /// </summary>
        public struct Achievement
        {
            public double MeritPay { get; set; }
            public string Level { get; set; }
            public double ReallyPay()
            {
                switch (Level)
                {
                    case "A":
                        MeritPay = MeritPay * 1.0;
                        break;
                    case "B":
                        MeritPay = MeritPay * 0.8;
                        break;
                    case "C":
                        MeritPay = MeritPay * 0.6;
                        break;
                    case "D":
                        MeritPay = 0;
                        break;
                    default:
                        MeritPay = 0;
                        break;
                };
                return MeritPay;
            }
        }

        static void Main(string[] args)
        {
            #region 泛型約束:值型別約束
            Achievement achievement = new Achievement
            {
                MeritPay = 500,
                Level = "B"
            };
            var result = GetReallyPay(achievement).ReallyPay();
            Console.WriteLine($"ReallyPay={result}");
            Console.Read();
            #endregion
        }

        /// <summary>
        /// 值型別約束
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static T GetReallyPay<T>(T t) where T : struct
        {
            return t;
        }
    }
View Code

    運行結果如下:

    7.5無引數建構式約束 new() 

    下面代碼演示無引數建構式約束:

    class Program
    {
        /// <summary>
        /// 運動類介面
        /// </summary>
        public interface ISports
        {
            void Pingpong();
        }

        /// <summary>
        /// 人類基類
        /// </summary>
        public class People
        {
            public string Name { get; set; }

            public virtual void Greeting()
            {
                Console.WriteLine("Hello World.");
            }
        }

        /// <summary>
        /// 中國人
        /// </summary>
        public class Chinese : People, ISports
        {
            public void FineTradition()
            {
                Console.WriteLine("自古以來,中華民族就保持著勤勞的優良傳統,");
            }
            public override void Greeting()
            {
                Console.WriteLine("吃飯了沒?");
            }

            public void Pingpong()
            {
                Console.WriteLine("乒乓球是中國的國球,");
            }
        }

        /// <summary>
        /// 廣東人
        /// </summary>
        public class Guangdong : Chinese
        {
            public Guangdong() { }
            public string Dialect { get; set; }
            public void Mahjong()
            {
                Console.WriteLine("這麻將上癮的時候,一個人也說是三缺一呀,");
            }
        }

        static void Main(string[] args)
        {
            #region 泛型約束:無引數建構式約束
            Guangdong guangdong = new Guangdong()
            {
                Name = "廣東人"
            };
            GetMahjong(guangdong);
            Console.Read();
            #endregion
        }

        /// <summary>
        /// 無引數建構式約束
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static T GetMahjong<T>(T t) where T : People, ISports, new()
        {
            if (t is Guangdong)
            {
                (t as Guangdong).Mahjong();
            }
            return t;
        }
    }
View Code

    運行結果如下:

    從上面可以看出,泛型約束可以有多個,但是有多個泛型約束時,new()約束要放到最后,

    八:泛型的協變和逆變

    協變和逆變是在.NET 4.0的時候出現的,只能放在介面或者委托的泛型引數前面,out協變covariant,用來修飾回傳值;in:逆變contravariant,用來修飾

傳入引數,

    下面代碼演示父類與子類的宣告方式:

    class Program
    {
        /// <summary>
        /// 動物基類
        /// </summary>
        public class Animal
        {
            public int Breed { get; set; }
        }

        /// <summary>
        /// 貓類
        /// </summary>
        public class Cat : Animal
        {
            public string Name { get; set; }
        }

        static void Main(string[] args)
        {
            #region 泛型的協變和逆變
            //直接宣告Animal類
            Animal animal = new Animal();
            //直接宣告Cat類
            Cat cat = new Cat();
            //宣告子類物件指向父類
            Animal animal2 = new Cat();
            //宣告Animal類的集合
            List<Animal> listAnimal = new List<Animal>();
            //宣告Cat類的集合
            List<Cat> listCat = new List<Cat>();
            #endregion
        }
    }
View Code

    以上代碼是可以正常運行的,假如使用下面的宣告方式,是否正確呢?

List<Animal> list = new List<Cat>();

    答案是錯誤的,因為List<Animal>和List<Cat>之間沒有父子關系,

    解決方法是使用協變的方式:

IEnumerable<Animal> List1 = new List<Animal>();
IEnumerable<Animal> List2 = new List<Cat>();

    按F12查看IEnumerable定義:

    可以看到,在泛型介面的T前面有一個out關鍵字修飾,而且T只能是回傳值型別,不能作為引數型別,這就是協變,使用協變以后,左邊宣告的是基類,

右邊的宣告可以是基類或者基類的子類,

    協變除了可以用在介面上面外,還可以用在委托上面:

Func<Animal> func = new Func<Cat>(() => null);

    除了使用.NET框架定義好協變以外,我們也可以自定義協變:

//使用自定義協變
ICustomerListOut<Animal> customerList1 = new CustomerListOut<Animal>();
ICustomerListOut<Animal> customerList2 = new CustomerListOut<Cat>();

    再來看看逆變

    在泛型介面的T前面有一個In關鍵字修飾,而且T只能方法引數,不能作為回傳值型別,這就是逆變,

/// <summary>
/// 逆變 只能是方法引數
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ICustomerListIn<in T>
{
     void Show(T t);
}

public class CustomerListIn<T> : ICustomerListIn<T>
{
     public void Show(T t)
     {
     }
}
View Code

    使用自定義逆變:

//使用自定義逆變
ICustomerListIn<Cat> customerListCat1 = new CustomerListIn<Cat>();
ICustomerListIn<Cat> customerListCat2 = new CustomerListIn<Animal>();

    協變和逆變也可以同時使用,

    下面代碼演示自定義協變與逆變:

    class Program
    {
        /// <summary>
        /// 動物基類
        /// </summary>
        public class Animal
        {
            public int Breed { get; set; }
        }

        /// <summary>
        /// 貓類
        /// </summary>
        public class Cat : Animal
        {
            public string Name { get; set; }
        }

        #region 泛型的自定義協變和逆變
        /// <summary>
        /// inT-逆變 outT-協變
        /// </summary>
        /// <typeparam name="inT"></typeparam>
        /// <typeparam name="outT"></typeparam>
        public interface IMyList<in inT, out outT>
        {
            void Show(inT t);
            outT Get();
            outT Do(inT t);
        }

        public class MyList<T1, T2> : IMyList<T1, T2>
        {

            public void Show(T1 t)
            {
                Console.WriteLine(t.GetType().Name);
            }

            public T2 Get()
            {
                Console.WriteLine(typeof(T2).Name);
                return default(T2);
            }

            public T2 Do(T1 t)
            {
                Console.WriteLine(t.GetType().Name);
                Console.WriteLine(typeof(T2).Name);
                return default(T2);
            }
        }
        #endregion

        static void Main(string[] args)
        {
            #region 泛型的自定義協變與逆變
            IMyList<Cat, Animal> myList1 = new MyList<Cat, Animal>();
            IMyList<Cat, Animal> myList2 = new MyList<Cat, Cat>();          //協變
            IMyList<Cat, Animal> myList3 = new MyList<Animal, Animal>();    //逆變
            IMyList<Cat, Animal> myList4 = new MyList<Animal, Cat>();       //逆變+協變
            myList1.Get();
            myList2.Get();
            myList3.Get();
            myList4.Get();
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    九、泛型快取

    類中的靜態型別無論實體化多少次,在記憶體中只會有一個,靜態建構式只會執行一次,在泛型類中,T型別不同,每個不同的T型別,都會產生一個不同

的副本,所以會產生不同的靜態屬性、不同的靜態建構式,

    下面代碼演示泛型快取:

    class Program
    {
        /// <summary>
        /// 泛型快取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class GenericCache<T>
        {
            private static readonly string TypeTime = "";
            static GenericCache()
            {
                Console.WriteLine("這個是泛型快取的靜態建構式:");
                TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
            }
            public static string GetCache()
            {
                return TypeTime;
            }
        }

        /// <summary>
        /// 泛型快取測驗類
        /// </summary>
        public class GenericCacheTest
        {
            public static void Show()
            {
                for (int i = 0; i < 5; i++)
                {
                    Console.WriteLine(GenericCache<int>.GetCache());
                    Thread.Sleep(10);
                    Console.WriteLine(GenericCache<long>.GetCache());
                    Thread.Sleep(10);
                    Console.WriteLine(GenericCache<DateTime>.GetCache());
                    Thread.Sleep(10);
                    Console.WriteLine(GenericCache<string>.GetCache());
                    Thread.Sleep(10);
                    Console.WriteLine(GenericCache<GenericCacheTest>.GetCache());
                    Thread.Sleep(10);
                }
            }
        }

        static void Main(string[] args)
        {
            #region 泛型快取
            GenericCacheTest.Show();
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    從上面的截圖中可以看出,泛型會為不同的型別都創建一個副本,因此靜態建構式會執行5次,另外每次靜態屬性的值都是一樣的,利用泛型的這一特性,可以實作快取,

    注:只能為不同的型別快取一次;泛型快取比字典快取效率高;泛型快取不能主動釋放,

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/87762.html

標籤:C#

上一篇:UpdatePanel 里面放了個Datalist 然后AspNetPager 分頁點擊無效

下一篇:[譯]C# 7系列,Part 9: ref structs ref結構

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more