c#編碼註釋

来源:https://www.cnblogs.com/arthuryao/archive/2019/07/09/11157106.html
-Advertisement-
Play Games

1 目錄 1 目錄 2 前言... 3 2.1 編寫目的... 3 2.2 適用範圍... 4 3 命名規範... 4 3.1 命名約定... 4 3.1.1 PascalCasing. 4 3.1.2 camelCasing. 4 3.1.3 UPPER_CAPS. 4 3.1.4 私有變數的命名 ...


 

 

 

 

 

 

 

 

 

 

 

 

 

 

1      目錄

2       前言... 3

2.1        編寫目的... 3

2.2        適用範圍... 4

3       命名規範... 4

3.1        命名約定... 4

3.1.1         PascalCasing. 4

3.1.2         camelCasing. 4

3.1.3         UPPER_CAPS. 4

3.1.4         私有變數的命名... 4

3.1.5         首字母縮寫詞的大小寫... 4

3.1.6         複合詞的大小寫... 5

3.2        命名選擇... 5

3.2.1         名字一定要能夠表達出標識符的含意... 5

3.2.2         命名要與使用者的期望相匹配... 6

3.2.3         不要賣弄風騷... 6

3.3        命名最佳實踐... 6

3.3.1         命名空間... 6

3.3.2         要讓介面的名字以字母I開頭... 6

3.3.3         派生類的末尾使用基類名稱... 7

3.3.4         泛型類型參數的命名... 7

3.3.5         枚舉類型的命名... 7

3.3.6         屬性的命名... 7

3.3.7         事件的命名... 7

3.3.8         欄位的命名... 8

4       註釋... 8

4.1        註釋約定... 8

4.1.1         類註釋約定... 8

4.1.2         類屬性註釋約定... 8

4.1.3         方法註釋約定... 8

4.1.4         代碼間註釋約定... 9

4.1.5         強制註釋的約定... 9

4.2        不需要的註釋... 9

4.2.1         不要為了註釋而註釋... 10

4.2.2         不要用註釋來粉飾糟糕的代碼... 10

4.2.3         日誌式註釋... 10

4.2.4         個人簽名... 11

4.2.5         位置標識... 11

4.2.6         註釋掉的代碼... 11

4.3        需要的註釋... 11

4.3.1         記錄你對代碼有價值的見解... 11

4.3.2         為代碼中的不足寫註釋... 11

4.3.3         對意料之中的疑問添加註釋... 12

4.3.4         公佈可能的陷阱... 12

4.3.5         對於代碼塊總結性地註釋... 12

4.4        如何寫好註釋... 13

4.4.1         避免使用不明確的代詞... 13

4.4.2         精確描述方法的行為... 13

4.4.3         用輸入輸出例子來說明特殊的情況... 13

4.4.4         更新代碼時記得更新註釋... 14

4.4.5         只有能讓別人讀懂的註釋才是合格的註釋... 14

4.5        region的使用... 14

4.6        c#中巧用#if debug進行調試... 14

4.7        c#特性代碼簡潔... 14

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2      前言

2.1    編寫目的

為了保證大家編寫出的程式都使用統一的風格,以方便閱讀和後期維護。

編碼規範對於程式員而言尤為重要,有以下幾個原因:

  1. 一個軟體的生命周期中,80%的花費在於維護。
  2. 幾乎沒有任何一個軟體,在其整個生命周期中,均由最初的開發人員來維護。
  3. 編碼規範可以改善軟體的可讀性,可以讓程式員儘快而徹底地理解新的代碼 。
  4. 編碼規範可以保證代碼閱讀者在閱讀代碼時產生儘可能少的歧義。
  5. 編碼規範可以使我們的代碼統一、美觀,讓客戶可以一眼看出我們是專業的團隊。

 

編碼規範的核心出發點是

  1. 讓其他人能夠快速,準確的知道代碼的作用並且確保不會出現歧義(其他人也包括一段時間後的自己)
  2. 讓我們的代碼看著更加清晰、美觀、專業、統一。

2.2    適用範圍

本公司內部開發人員

 

3      命名規範

任何標識符的名字都應該可以簡單、清楚、正確的表示出該標識符的作用。

同時我們要將儘可能多的信息裝入到標識符的名字當中去,以便讀代碼的人可以快速的讀懂代碼。

3.1    命名約定

我們在命名標識符時(包括參數,常量,變數),應使用單詞的首字母大小寫來區分一個標識符中的多個單詞,如UserName.

3.1.1    PascalCasing

PascalCasing包含一到多個單詞,每一個單詞第一個字母大寫,其餘字母均小寫。例如:HelloWorld、SetName等。

除了參數、變數、常量外,所有命名空間名稱、類、函數、介面、屬性、事件、枚舉等名稱的命名,使用 Pascal 風格。

3.1.2    camelCasing

camelCasing包含一到多個單詞,第一個單詞首字母小寫,其餘單詞首字母大寫。例如:name、productId等。

參數與變數的命名使用camelCasing.

3.1.3    UPPER_CAPS

UPPER_CAPS包含一到多個單詞,每個單詞的所有字母都大寫,單詞與單詞之間用”_”連接,該風格目前在c#中只用於const常量。

如:public const string DEFAULT_PAGE = "default.aspx";

3.1.4    私有變數的命名

Private 的私有變數使用下劃線”_”+camelCasing的大小寫規則,以便快速確認該變數的作用域。

如:  private int _userId;

3.1.5    首字母縮寫詞的大小寫

首字母縮寫詞是由一個短語的首字母組成的,如Xml(ExtensibleMarkuLaguage),IO(Input and Output)。它和單詞縮寫是有區別的,單詞縮寫僅僅是把一個單詞的長度變短。

  1. 把兩個字母的首字母縮寫詞全部大寫,除非它是camelCasing的第一個單詞。

using System.IO;

public void StartIO(Stream ioStream)

  1. 由三個或以上的字母組成的首字母縮寫詞,只有第一個字母大寫,如Xml,Html.除非首字母是camelCasing標識符的第一個單詞。

using System.Xml;

public void ProcessXmlNode(XmlNode xmlNode)

3.1.6    複合詞的大小寫

不要把複合詞中的首字母大寫。複合詞要當成一個單詞來處理。

如endpoint, callback,metadata,namespace等都是正確的寫法

3.2    命名選擇

3.2.1    名字一定要能夠表達出標識符的含意

標識符名字必須要表達出該標識符的意義,絕對不可以使用無意義的v1,v2…vn之類的命名。

        public static void CloneChars(char[] cl1, char[] cl2)

        {

            for (var i = 0; i < cl1.Count(); i++)

            {

                cl2[i] = cl1[i];

            }

        }

代碼的調用者不看這函數是無法知道cl1還是cl2是要拷貝的char數組,他必須進到這個函數去看完整個邏輯才可以調用。而且在看的過程中cl2[i] = cl1[i]; 也需要他花幾秒鐘來思考是做什麼的。

如果改成有意義的名字: source 和target那麼這個方法調用者一看名字就知道使用方法了。

   public static void CloneChars(char[] source, char[] target)

        {

            for (var i = 0; i < source.Count(); i++)

            {

                target[i] = source[i];

            }

        }

 

在給標識符命名時,一定不能產生歧義,代碼中的很多錯誤都是由於命名時的歧義造成的。例如:

public const int CART_TOO_BIG_LIMIT = 10;

if (ShoppingCart.Count() >= CART_TOO_BIG_LIMIT)

            {

                LogError("Too many items in cart.");

            }

3.2.2    命名要與使用者的期望相匹配

有些名字之所以會讓人誤解是因為帶嗎閱讀者對它們有先入為主的印象,就算你本意並非如此。這種情況下,你最好是選用一個與使用者期望所匹配的名字。

如很多程式員都習慣了把Get開始的方法當作“輕量級訪問器“,他只是簡單的返回成員變數。

大家看到以下的代碼

    class BinaryTree

    {

        public int GetNodesCount()

會以為只是返回內部private int _nodesCount; 私有變數的訪問器。

但如果實際你的代碼可能是一個非常耗時的代碼,內部實現是廣度優先遍歷所有的樹節點,還要去資料庫查找父節點和子節點的關係,然後累加。

那麼這麼一個耗時的方法可能由於你的命名,導致了被調用者反覆多次的調用,導致整個系統性能下降。

如果你將命名改為ComputeNodesCount那麼調用者就會知道這是個耗時的操作,需要緩存調用結果並減少調用。

3.2.3    不要賣弄風騷

使用最常用,眾所周知的單詞。不要在代碼命名時賣弄你的學識,要讓你的代碼快速準確的表達出你的想法才是真正的牛人。

如public static string ConvertXml2Html (string sourcePath)

有些人在看到這個方法的時候怎麼想也想不明白這個2是做什麼用的,是把一個Xml文件變成兩個Html?

熟悉英語文化的人可能知道這是To的俚語表達。如果你不能保證所有閱讀你代碼的人都知道2是To的縮寫。那麼請使用ConvertXmlToHtml命名。

 

3.3    命名最佳實踐

3.3.1    命名空間

  1. 要使用PascalCasing,並用點號來分隔名字空間中的各個部分。

如Microsof.Office.PowerPoint

3.3.2    要讓介面的名字以字母I開頭

如IComponet,IDisposable 大家一看就知道是介面。

同時要確保如果一個類是一個介面的標準實現,那麼這個類和介面應該只差一個”I“首碼。

3.3.3    派生類的末尾使用基類名稱

例如,從 Stream 繼承的 Framework 類型以 Stream 結尾,從 Exception 繼承的類型以 Exception 結尾。

3.3.4    泛型類型參數的命名

  1. 使用描述性的名字來命名泛型類型參數,並且在前面加上T首碼

如下麵都是很好的命名

public delegate TOutput Converter<TInput, TOutput>(TInput from);

  1. 如果只有一個類型參數,可以只用一個字母T來表示泛型

public class Nullable<T>

public class List<T>

  1. 如果泛型參數有約束,那麼需要在泛型類型參數名中需要顯示出該約束

public interface ISessionChannel<TSession> where TSession:ISession

3.3.5    枚舉類型的命名

  1. 要用單數名詞而不是複數命名枚舉類型,如要用ConsoleColor而不是ConsoleColors

public enum ConsoleColor

    {

        Red,

        Yellow,

        Blue

}

  1. 不要給枚舉類型加”Enum“、”Flag”等尾碼。

ColorEnum,ColorFlag都不好,因為本身就是枚舉,再加上就是沒有意義的重覆 。

3.3.6    屬性的命名

  1. 要用名詞、名詞短語或形容詞來命名屬性
  2. 要用描述集合中具體內容的短語的複數形式來命名屬性集合,而不要用短語的單數形式加”List“、”Array”或”Collection“尾碼

class BinaryTree

    {

        //Good Naming

        public NodeCollection Nodes { get; set; }

 

        //Bad Naming

        public NodeCollection NodesCollection { get; set; }

  1. 要用肯定性的短語命名布爾屬性。最好在前面選擇性的加入”Is“、”Can“、”Has“等首碼。

CanSeek比CantSeek和Seekable都更準確和容易理解。

3.3.7    事件的命名

  1. 要用動詞或動詞短語命名事件

如: Clicked、Painting、DroppedDown 等等

  1. 要用現在進行時(ing)和過去式(ed)來賦予事件發生之前和之後的概念。而不是使用Before和After.

如視窗關閉前發生的close事件應該命名為Closing,而在視窗關閉之後發生的應該命名為Closed.

3.3.8    欄位的命名

  1. 禁止使用實例的公有欄位和受保護欄位,請使用屬性代替。

Tips:在VisualStudio中輸入”prop”可快速創建外部可修改的屬性,輸入”propg”可快速創建不允許外部修改的屬性。如:

        //prop

        public int NodesCount { get; private set; }

        //propg

        public List<BinaryNode> Nodes { get; set; }

  1. 一般只使用靜態欄位
  2. 要使用名詞、名詞短語或形容詞命名欄位
  3. 不要給欄位加首碼如“g_”、”s_”來表示靜態欄位。因為欄位和屬性是非常相似的,所以要遵循相同的命名規範。

 

4      註釋

註釋毫無疑問是讓別人以最快速度瞭解你代碼的最快途徑,但寫註釋的目的絕不僅僅是”解釋代碼做了什麼“,更重要的儘量幫助代碼閱讀者對代碼瞭解的和作者一樣多。

當你寫代碼時,你腦海裡會有很多有價值的信息,但當其他人讀你代碼時,這些信息已經丟失,他們所見到的只是眼前代碼。

4.1    註釋約定

如果IDE提供註釋格式,則儘量使用IDE提供的格式,否則使用”//”來註釋。類、屬性和方法的註釋在Visual Studio中都使用輸入”///”自動生成的格式。

4.1.1    類註釋約定

///<summary>

    ///角色信息

    ///</summary>

    public  class  CarRoleModel

4.1.2    類屬性註釋約定

///<summary>

     ///角色id

     ///</summary>

     publicstring RoleId { get; set; }

4.1.3    方法註釋約定

///<summary>

     ///用戶登錄

     ///</summary>

     ///<param name="userName">用戶名</param>

     ///<param name="password">密碼</param>

     ///<returns>返回用戶登錄結果</returns>

     public ActionResult SubmitLogin(string userName, string password)

4.1.4    代碼間註釋約定

  1. 單行註釋,註釋行數<3行時使用

//單行註釋

  1. 多行註釋,2<註釋行數<=10時使用

/*多行註釋1

多行註釋2

多行註釋3*/

  1. 註釋塊,10<註釋行數時使用,用50個*

/***************************************************

         *  代碼塊註釋1

         * 代碼塊註釋2

         * ......

         * 代碼塊註釋10

         * 代碼塊註釋11

***************************************************/

4.1.5    強制註釋的約定

  1. 以下三種情況我們需要在所有的類、類屬性和方法都必須按照上述格式編寫註釋

1)  客戶方對代碼註釋重視程度較高

2)  我們需要提供代碼註釋自動生成的API文檔。

 

3) 目前編寫的是公共核心模塊

  1. 如果客戶方沒有對註釋特殊要求,那麼按照下文中討論的只在需要的地方加註釋。不要加無謂的註釋。

4.2    不需要的註釋

 

閱讀註釋會占用閱讀真實代碼的時間,並且每條註釋都會占用屏幕上的空間。所以我們約定所加的註釋必須是有意義的註釋,否則不要浪費時間和空間。

區別要不要寫註釋的核心思想就是:不要為那些能快速從代碼本身就推斷的事實寫註釋。

4.2.1    不要為了註釋而註釋

有些人可能以前的公司對於註釋要求很高,如“何時寫註釋”章節中的要求。所以很多人為了寫註釋而註釋。

再沒有特殊要求的情況下我們要禁止寫下麵這種沒有意義的註釋。

    /// <summary>

    /// The class definition for Account

    /// </summary>

    public class BinaryTree

    {

        /// <summary>

        /// Total counts of the nodes

        /// </summary>

        public int NodesCount { get; private set; }

        /// <summary>

        /// All the nodes in the tree

        /// </summary>

        public List<BinaryNode> Nodes { get; set; }

 

       /// <summary>

       /// Insert a node to the tree

       /// </summary>

       /// <param name="node">the node you want insert into the tree</param>

        public void InsertNode(BinaryNode node)

4.2.2    不要用註釋來粉飾糟糕的代碼

寫註釋常見的動機之一就是試圖來使糟糕的代碼能讓別人看懂。對於這種“拐杖式註釋”,我們不需要,我們要做的是把代碼改的能夠更具有”自我說明性“。

記住:“好代碼>壞代碼+好註釋”

如下麵這段函數的註釋

        //Enforce limits on the reply as stated in the request

        //such as the number of items returned, or total byte size,etc.

        public void CleanReply(Request request,Reply reply)

既然知道這個函數名會讓人很難讀懂,那麼為什麼不直接改好名字呢?這樣所有調用這個函數的地方都能很快速知道這個函數的作用,不用再跟進來看函數的作用。

public  void EnforceLimitsFromRequestOnReply(Request request,Reply reply)

4.2.3    日誌式註釋

有人喜歡在每次編輯代碼時,都在模塊開始處加一條註釋。這類註釋就像是一種記錄每次修改的日誌。在很久以前這種記錄對於維護還有意義。但是對於現在的源碼控制來說,這些記錄完全是冗餘的,需要完全廢除。

         /***************************************************

         *    July-29-2014:Fix Bug-12345: Add new method to calculate nodes count

         *   July-20-2014:Fix Bug-11111: Add Insert new node method

         *   ......

         *   July-20-2014:Task-00001: Create BinaryTree class

        ***************************************************/

4.2.4    個人簽名

//Added By XXXX

有人認為這種註釋有助於不瞭解這段代碼含意的人和他討論。事實上確是這條註釋放在那一年復一年,後來的代碼和原作者寫的源碼越來越不一樣,和XXXX也越來越沒關係。

重申一下,TFS里都能看到這類信息,不要加在代碼里。

4.2.5    位置標識

        //AddNodePlace1

        //AddNodePlace2

有人喜歡在代碼註釋裡加入位置標識以方便他查找代碼的位置。

現在的IDE都集成了這些功能,如VS中可以使用Bookmark(Ctrl+b,t)。

不要將這類註釋加到代碼中。

4.2.6    註釋掉的代碼

直接把代碼註釋掉是非常令人討厭的做法。

其他人不敢刪掉這些代碼。他們會想代碼依然在這一定是有原因的,而且這段代碼很重要,不能刪除。而且每個閱讀代碼的人都會去看一下這些被註釋掉的代碼中是否有他們需要註意的信息。

這些註釋掉的代碼會堆積在一起,散髮著腐爛的惡臭。

4.3    需要的註釋

4.3.1    記錄你對代碼有價值的見解

你應該在代碼中加入你對代碼這段代碼有價值的見解註釋。

如:    //出乎意料的是,對於這些數據用二叉樹比哈希表要快40%

        //哈希運算的代價比左右比要大的多

這段註釋會告訴讀者一些重要的性能信息,防止他們做無謂的優化。

4.3.2    為代碼中的不足寫註釋

代碼始終在演進,並且在代碼中肯定會有不足。

要把這些不足記錄下來以便後來人完善。

如當代碼需要改進時:

//TODO:嘗試優化演算法

如當代碼沒有完成時:

//TODO:處理JPG以外的圖片格式

你應該隨時把代碼將來該如何改動的想法用註釋的方式記錄下來。這種註釋給讀者帶來對代碼質量和當前狀態的寶貴見解,甚至會給他們指出如何改進代碼的方向。

4.3.3    對意料之中的疑問添加註釋

當別人讀你的代碼的時候,有些部分可能讓他們有這樣的疑問:“為什麼要這樣寫?”你的工作就是要給這些部分加上註釋。

如:      

        // 因為Connection的創建很耗費資源和時間,而且需要多線程訪問,

        // 所以使用多線程單例模式

        public static Connection Instance

        {

            get

            {

                if(_instance==null)

                {

                    lock (_lock)

                    {

                        if (_instance == null)

                        {

                            _instance = new Connection();

                        }

                    }

                }

                return _instance;

            }

        }

4.3.4    公佈可能的陷阱

當為一個函數或者類寫註釋時,可以這樣的問自己:”這段代碼有什麼出人意料的地方嗎?會不會被無用?“。基本上說就是你需要未雨綢繆,預料到別人使用你代碼時可能遇到的問題。如:

        //XXX: 因為調用外部郵件伺服器發送郵件,所以耗時較長,請使用非同步方法調用以防止UI卡死。

        public void SendEmail(string to, string subject, string body)

4.3.5    對於代碼塊總結性地註釋

對於代碼塊的總結性註釋可以使讀者在深入細節之前就能得到該代碼塊的主旨,甚至有時候都可以直接跳過該代碼塊,從而可以快速準確的把握代碼。

如讀者看到://下麵代碼使用了二分查找演算法來快速的根據用戶Id找到相應用戶

那麼他就可以快速理解下麵代碼的邏輯,否則自己看二分查找還是要用些時間的。

4.4    如何寫好註釋

4.4.1    避免使用不明確的代詞

有些情況下,”it”, “this”等代詞指代很容易產生歧義,最安全的方式是不要使用將所有可能產生歧義的代詞替換成實際指代的詞。

如://Insert the data into the cache,but check if it's too big first.

”it”是指”data“還是”cache“? 在讀完剩下的代碼前誰也不知道指代的是誰。那還要註釋做什麼?替換成要指代的詞後讀者就可以直接了當的知道接下來的代碼要做什麼了。

//Insert the data into the cache,but check if the data is too big first.

4.4.2    精確描述方法的行為

註釋一定要精確的描述方法的行為。避免由於註釋不准確而造成的誤調用。

如你寫了一個方法統計文件中的行數

        //Return the number of lines in this file

        public long CountLinesInFile(string fileName)

上面的註釋不是很精確,因為有很多定義行的方式,下麵幾種情況這個方法的返回值無法根據註釋快速的判斷出來。

  1. “”(空文件)——0或1行?
  2. “hello”­­——0或1行?
  3. “hello\n”­­——1或2行?
  4. “hello\n\r world\r”­­——2、3或4行?

假設該方法的實現是統計換行符的(\n)的個數,下麵的註釋就要比原來的註釋更好些。

//Count how many newline symbols('\n') are this file

這條註釋包含更多的信息。讀者可以知道如果沒有換行符,這個函數會返回0。讀者還知道回車符(\r)會被忽略。

4.4.3    用輸入輸出例子來說明特殊的情況

對於註釋來講,一個精挑細選的例子比千言萬語還要有效,而且更加直白有效,閱讀速度更快。

如:        /// <summary>

        /// Remove the suffix/prefix of charsToRemove from the input source

        /// </summary>

        public string StripPrefixAndSuffix(string source, string charsToRemove)

這條註釋不是很精確,因為它不能回答下麵的問題

  1. 是只有按charsToRemove中順序的字元才會被移除,還是無序的charsToRemove也會被移除?
  2. 如果在開頭和結尾有多個charsToRemove會怎樣?

而一個好例子就可以簡單直白的回答這些問題:

 /// <summary>

        /// Example: StripPrefixAndSuffix("abbayabbazbaba","ab") returns "yababz"

        /// </summary>

4.4.4    更新代碼時記得更新註釋

再好的註釋也會隨著內容的更改而變得越來越沒有意義,有時候甚至會對讀者造成誤導,產生不必要的bug。所以在更改代碼後,記得要更新所更改代碼的註釋,使其表達最新代碼的含意。

4.4.5    只有能讓別人讀懂的註釋才是合格的註釋

當自己不確定自己的註釋是否合格時,請周圍的同事讀下你的註釋,看他讀完註釋後說出的想法是否是你想要表達的,是否有信息遺漏和誤解等。

4.5    region的使用

如下圖所示:

 

4.6    c#中巧用#if debug進行調試

#if DEBUG

    UserID = "[email protected]";

    Password = "123456";

#endif

當調試代碼的時候加上適當的判斷,而不影響Release的代碼。

通過#if預編譯指令對DEBUG進行判斷,如下:

#if DEBUG

  // 調試用代碼

   ……#endif

調試用代碼在Debug狀態下是要執行的,而在Release狀態下根本執行,在生成的時候也直接忽略。

4.7    c#特性代碼簡潔

  1.var car_Permission = _car_PermissionBusiness.GetModel(car_User.RoleID) ?? null;

 

  2.var car_Permission = _car_PermissionBusiness.GetModel(car_User.RoleID) == null ? new Car_Permission() : _car_PermissionBusiness.GetModel(car_User.RoleID);

 

  3.var userName= _car_UserBusiness.GetCarUser(car_User.RoleID)?.UserName ?? null;

總結:第一種跟第二種獲取的數據方法是一樣的

 


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

-Advertisement-
Play Games
更多相關文章
  • 7.13 元類 元類:類的類就是元類,我們用class定義的類來產生我們自己的對象的,內置元類type是用來專門產生class定義的類 7.131 用內置的元類type,來實例化得到我們的類 7.132 __call__方法 在調用對象時自動觸發__call__的執行 7.133 自定義元類來控制類 ...
  • 恢復內容開始 需求:輸出所有的”水仙花數” 所謂的水仙花數是指一個三位數,其各位數字的立方和等於該數本身。 舉例:153就是一個水仙花數。 153 = 111 + 555 + 333 = 1 + 125 + 27 = 153 所謂的水仙花數是指一個三位數,其各位數字的立方和等於該數本身。 結果: 恢 ...
  • 之前面了騰訊的提前批,不過沒走流程。同期還面了阿裡的兩輪面試,被告知不走流程就不能面了,所以也沒面完。 後來走了京東這邊的流程。前幾天剛剛面完HR。 正好今天分享一下麵經,大家可以多交流交流哈。 京東面經 第一輪:電話初面 第二輪:技術面談 第三輪:高管覆試 第四輪:HR最後確認 第一輪電話初面: ...
  • 在這一篇文章(abp(net core)+easyui+efcore實現倉儲管理系統——展現層實現增刪改查之列表視圖(七))中我們創建一個使用Razor視圖引擎的視圖模板文件,Razor視圖模板文件的擴展名為.cshtml,並提供一種比較優雅的方式使用C#來創建HTML輸出。Razor視圖模板減少了... ...
  • 最近在學習WCF通信,自己簡單做個實例分享一下,環境是VS2015,使用的項目都是WPF的項目,其實大家用Winform或者Web項目也可以,都可以用的。 一、伺服器端 1、創建WCF服務 服務名為WCFServer,而後自動生成如下兩個文件,IMyWCFServer為服務契約介面,MyWCFSer ...
  • 題目描述 跳臺階:一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(先後次序不同算不同的結果)。變態跳臺階:一隻青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。矩形覆蓋:我們可以用21的小矩形橫著或者豎 ...
  • LnskyDB是基於Dapper的Lambda擴展,支持按時間分庫分表,也可以自定義分庫分表方法.而且可以T4生成實體類免去手寫實體類的煩惱. v2.0版本支持多表查詢了 ...
  • 題目描述 大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項為0)。 n<=39 解題思路 遞推公式f(n)=f(n)= 當n=0=0,當n=0 當n=1=1,當n=1 其他=f(n−1)+f(n−2)看到這大家很容易想起遞歸,課堂上老師講遞歸的時候的經典 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...