2017年7月31日 星期一

[C#] Try Catch Finally issue

  • try-catch
    • 超出一般控制流程的程式碼會處理這些例外狀況
    • throw 
      • 在程式執行期間發出出現例外狀況的訊號
      • 拋出捕抓到的例外
      • Code
                  try
                  {
                      // throw 的訊息會導引至 catch 中顯示
                      if (sName.Equals("Lyndon"))
                          throw new ApplicationException("DemoError");
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine("Error: {0}", e.Message);
                  }
    • try-catch-finally
      • finally 
        • 選擇性區塊
        • finally 中的程式無論如何都會執行 
        • 通常將釋放資源的程式寫在 finally 中
      • Code
                  try
                  {
                      // try 區塊中的資源、處理
                  }
                  catch (Exception e)
                  {
                      // catch 區塊中的例外情況
                  }
                  finally
                  {
                      // 釋放 try 區塊中所使用的資源
                      // 撰寫 finally 區塊
                      // 1. 程式執行順序最後一定會跑至 finally 區塊
                      // 2. 如 try / catch 區塊中,使用 return,finally 區塊還是會被執行
                  }
  • try-catch block
    • Code
    
    public class TryCatchPerformanceLib
        {
    public int nCount = 1000000;
            public long lSum = 0;
            public bool flag = false;
            public int nDiv = 100000;
            public int nDiv2 = 200000;
    
            /// 
            /// Case1: no try catch
            /// 
            /// Sum number
            public long Case1()
            {
                lSum = 0;
                for (int i = 0; i < nCount; i++)
                {
                    lSum += i;
                    if (i % nDiv == 0)
                        flag = true;
                }
    
                return lSum;
            }
    
            /// 
            /// Case2: try catch
            /// 
            /// Sum number
            public long Case2()
            {
                lSum = 0;
                for (int i = 0; i < nCount; i++)
                {
                    try
                    {
                        lSum += i;
                        if (i % nDiv == 0)
                            flag = true;
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Error: {0}", e.Message);
                    }
                }
    
                return lSum;
            }
    
            /// 
            /// Case2: try catch and one exception
            /// 
            /// Sum number
            public long Case3()
            {
                lSum = 0;
                for (int i = 0; i < nCount; i++)
                {
                    try
                    {
                        lSum += i;
                        if (i % nDiv == 0)
                            throw new ApplicationException("DemoError");
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Error: {0}", e.Message);
                    }
                }
    
                return lSum;
            }
    
            /// 
            /// Case2: try catch and one exception (reduce frequency)
            /// 
            /// Sum number
            public long Case4()
            {
                lSum = 0;
                for (int i = 0; i < nCount; i++)
                {
                    try
                    {
                        lSum += i;
                        if (i % nDiv2 == 0)
                            throw new ApplicationException("DemoError");
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Error: {0}", e.Message);
                    }
                }
    
                return lSum;
            }
        }
    • Result
      • Case1 Sum=499,999,500,000 Time=11ms
      • Case2 Sum=499,999,500,000 Time=11ms
      • Case3 Sum=499,999,500,000 Time=121ms
      • Case4 Sum=499,999,500,000 Time=45ms
    1. try…catch 只有在發生 Exception 時才會影響效能
    2. 當 catch 越頻繁影響效能越嚴重
  • Ref:
    • http://blog.darkthread.net/post-2009-12-20-try-catch-performance.aspx
    • http://blog.darkthread.net/blogs/darkthreadtw/archive/2007/11/14/kb-how-avoidable-try-catch-tortures-your-machine.aspx
    • https://dotblogs.com.tw/yc421206/archive/2011/06/09/27445.aspx
    • https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/keywords/exception-handling-statements
    • http://teddy-chen-tw.blogspot.tw/2013/11/javatrycatchfinally1java-se-7.html

2017年7月30日 星期日

[C#] Feature introduced in C# 2.0

  • Feature introduced in C# 2.0
  • Feature introduced
    • Generics 泛型 (C# 程式設計手冊)
      • 泛型型別參數 T
      • Code
      
      // Declare the generic class.
      public class GenericList< t>
      {
          void Add(T input) { }
      }
      class TestGenericList
      {
          private class ExampleClass { }
          static void Main()
          {
              // Declare a list of type int.
              GenericList< int> list1 = new GenericList< int>();
      
              // Declare a list of type string.
              GenericList< string> list2 = new GenericList< string>();
      
              // Declare a list of type ExampleClass.
              GenericList< exampleclass> list3 = new GenericList< exampleclass>();
          }
      }
    • Anonymous
 Methods 匿名函式 (C# 程式設計手冊)
      • 匿名函式是可用於任何需要委派類型之處的「內嵌」陳述式或運算式
      • Code
      
      class Test
      {
          delegate void TestDelegate(string s);
          static void M(string s)
          {
              Console.WriteLine(s);
          }
      
          static void Main(string[] args)
          {
              // Original delegate syntax required 
              // initialization with a named method.
              TestDelegate testDelA = new TestDelegate(M);
      
              // C# 2.0: A delegate can be initialized with
              // inline code, called an "anonymous method." This
              // method takes a string as an input parameter.
              TestDelegate testDelB = delegate(string s) { Console.WriteLine(s); };
      
              // C# 3.0. A delegate can be initialized with
              // a lambda expression. The lambda also takes a string
              // as an input parameter (x). The type of x is inferred by the compiler.
              TestDelegate testDelC = (x) => { Console.WriteLine(x); };
      
              // Invoke the delegates.
              testDelA("Hello. My name is M and I write lines.");
              testDelB("That's nothing. I'm anonymous and ");
              testDelC("I'm a famous author.");
      
              // Keep console window open in debug mode.
              Console.WriteLine("Press any key to exit.");
              Console.ReadKey();
          }
      }
      /* Output:
          Hello. My name is M and I write lines.
          That's nothing. I'm anonymous and
          I'm a famous author.
          Press any key to exit.
       */
      
    • Nullable Type 可為 Null 的類型 (C# 程式設計手冊)
      • 可為 Null 的型別是 System.Nullable<T> 結構的執行個體
      • 可為 Null 的型別可以代表其基礎值型別的正確值範圍,再加上額外的 null 值
      • Code
      
      /// 
      /// 使用 HasValue 成員先測試變數是否包含值,再嘗試顯示它
      /// 
      int? x = 10;
      if (x.HasValue)
      {
          System.Console.WriteLine(x.Value);
      }
      else
      {
          System.Console.WriteLine("Undefined");
      }
      
      
      /// 
      /// 使用 null 成員先測試變數是否包含值,再嘗試顯示它
      /// 
      int? y = 10;
      if (y != null)
      {
          System.Console.WriteLine(y.Value);
      }
      else
      {
          System.Console.WriteLine("Undefined");
      }
      
      
      /// 
      /// 明確轉換
      /// 
      int? n = null;
      
      //int m1 = n;      // Will not compile.
      int m2 = (int)n;   // Compiles, but will create an exception if n is null.
      int m3 = n.Value;  // Compiles, but will create an exception if n is null.
      
      • Code 2
      
              int? n = null;
              int m = 0;
              // 1. 一般判別
              if ( n == null )
                  m = 0;
              else 
                  m = n;
              // 2. (三元)運算子
              // https://msdn.microsoft.com/zh-tw/library/zakwfxx4(v=vs.100).aspx
              m = (n == null ? 0 : n);
      
              // 3. null 聯合運算子
              // https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/operators/null-conditional-operator
              m = n ?? n;
  • Ref:
    • https://www.slideshare.net/ssusercab70d/c35-55576724

[C#]Evolution History of C#

  • History 
  • C# 2.0 Detail
  • C# 3.0 Detail
  • C# 4.0 Detail
  • C# 5.0 Detail
  • C# 6.0 Detail
  • Ref:
    • https://msdn.microsoft.com/zh-tw/library/z1zx9t92(v=vs.110).aspx
    • https://zh.wikipedia.org/wiki/C%E2%99%AF

2017年7月29日 星期六

[C#] strongly typed, weakly typed (loosely typed)


  • 程式語言區別
  • 程式語言區別描述
    • 動態/靜態類型語言 (Static typing when possible, dynamic typing when needed)
      • 型態系統 (type system): 程序專門處理數據的系統,語言可分:
        1. 動態類型系統 (Dynamically Typed Systems)
          • Python, Ruby, ECMAScript(JavaScript)
        2. 靜態類型系統 (Statically Typed Systems)
          • C, C++, C#
          • 更進一步分為:
            1. 包含宣告型態 (manifest type),每個變量和函數型態都須清楚宣告
            2. type-inferred语言
              • MUMPS, ML
    • 四種類型語言分類及區別
      • 動態類型 (Dynamically Typed Language)
        • 運行期間才檢查數據類型(動態類型語言編譯時),永遠不用給任何邊量指定數據類型。第一次賦值給變量時,內部將數據類型記錄下來
        • Python, Ruby, PHP, ECMAScript(JavaScript)
        • Python 和 Ruby 是典型動態類型語言,其他像各種腳本語言如VBScript 也使屬於此類型
        • 優點:方便閱讀,不需要寫非常多的類型相關代碼
        • 缺點:不方便調試,命型沒規範時會照成閱讀問題,不利於理解 ... 等等
      • 靜態類型 (Statically Typed Language)
        • 編譯期間會檢查數據類型(撰寫程序時需聲明所有變量的數據類型),所有變數需聲明數據類型,且固定(int, float, double... 等)
        • C, C++ 為靜態類型語言的典型代表,其他還有 C#, JAVA ... 等等
        • 優點:結構非常有規範,便於調試,方便類型安全
        • 缺點:因此需要寫更多類型相關代碼,不便於閱讀、不清晰明瞭
      • 顯性類型 (Explicitly type conversion,類型安全)
        • 確實地告訴編譯器,這類型在做什麼
        • 一個變量指定某個數據類型,如果不經過強制轉換,它永遠就是這個數據類型
        • 必需進行變量/對象類型聲明的語言,一般情況下需要編譯執行
        • 舉例:若定義一個整數類型的變量 A,不進行轉換,A 將不能當作字串類型處理
        • C, C++, C#, JAVA, Python, Ruby
      • 隱性類型 (Implicitly type conversion,類型不安全)
        • 不希望編譯器來幫做轉型動作,或是為了解決某些困難,想要卸除編譯器安全限制,就可以使用顯性轉型來達到目的
        • 它與顯性轉型別相反,一個變量可以賦與不同的數據類型值
        • 舉例:如字串'12'和整數 3 進行連接得到字串 '123',結果可為整數 '123',而不需要轉換
        • PHP, ECMAScript(JavaScript), ... 
        • 注意:
          • “顯性轉型”在速度上可能略遜於“隱性轉型”
          • “顯性轉型”的嚴謹性能夠有效避免許多錯誤
    • 總結關於
      • “是否為動態語言”與“安全性”之間是全沒有關係
    • 舉例安全
      • Python 是動態語言,是顯性轉型 (類型安全)
      • JavaScript 是動態語言,是隱性轉型 (類型不安全)
      • JAVA 是靜態語言,是顯性轉型 (類型安全)
    • Code
    
    // Object  弱型別
    // 隱性轉型就是無法區分為型態的型別
    var obj = "Lyndon";
    
    // String 強型別
    // 能夠明確定義出型別的就是顯性轉型
    // 在編譯(complier)時就可以找出錯誤
    String sStr = "Lyndon"; 
    

  • 編譯與運行角度 (與上敘述語法角度區別有所不同)
    • 類型系統的觀念,眾說紛紜,使用上也比較混亂。有些東西,勝治不好嚴格定義。以下算是學術界另一種相對 “嚴格”的定義。
    • 定義基礎概念
      • Program Errors
        1. trapped errors
          • 導致程序終止執行 (如:除以 0,C#/Java 中數組越界訪問越界)
        2. untrapped errors
          • 出錯後繼續執行,但可能出現任意行為 (如:C 緩衝區溢出、Jump 到錯誤地址)
      • Forbidden Behaviors
        1. 語言設計時,可以定義一組 forbidden behaviors,它必須包括所有 untrapped errors,但可能包含 trapped errors。
      • Well behaved / ill behaved
        1. well behaved 
          • 如果程序執行不可能出現 forbidden behaviors,則為 well behaved 
        2. ill behaved:否則為 ill behaved
    • 有了上面概念,再討論“強弱型別” 與 “靜態動態類型”
      • 動態類型 (Dynamically Typed Language)
        • 如果運行時拒絕 ill behaviors,則是 dynamically typed
      • 靜態類型 (Statically Typed Language)
        • 如果編譯時拒絕 ill behaved,則是 statically typed
      • 強型類型 (Strongly typed)
        • 如果語言所有程序都是 well behaved,即不可能出現 forbidden behaviors,則該語言為 strongly typed
      • 弱型類型 (Weakly typed)
        • 否則為 weakly typed (如:C 語言的緩衝區溢出,屬於 untrapped errors,屬於 forbidden behaviors,因此 C 為弱類型)
      • 前面說明,弱型別語言,類型檢查更不嚴格
        • 偏向容忍隱式類型轉換(如:C 語言 int 可以換成 double。這樣結果是容易產生 forbidden behaviours,所以是弱型別)
    • 誤區
      • C 語言撰寫 int a,int b 之類,Python 不用寫 (可以直接撰寫 a,b),所以C 是靜態,Python 是動態。這麼理解是不夠準確 (如:OCaml 是靜態隱式類型,但可以不用明確撰寫出來)
      • 靜態類型可以分兩種:
        1. 如果類型是語言語法一部分,是顯示類型 (explicitly typed)
        2. 如果類型通過編譯時推導,是隱式類型 (implicitly typed)  (如:ML和Haskell)
    • 例子

      • 無類型:匯編 
      • 弱類型、靜態類型:C/C++ 
      • 弱类型、動態類型檢查:Perl/PHP 
      • 強型別、靜態類型檢查:Java/C# 
      • 強型別、動態類型檢查:Python,Scheme 
      • 靜態顯示類型 :Java/C 
      • 靜態隱式類型 :OCaml,Haskell
    • 補充
      • 紅色區域外:well behaved (type soundness) 
      • 紅色區域內:ill behaved 
      • 如果所有程序都是灰的:strongly typed 
      • 否則如果存在紅色的程序:weakly typed 
      • 編譯時排除紅色程序:statically typed 
      • 運行時排除紅色程序:dynamically typed 
      • 所有程序都在黃框以為:type safe 

  • 結論
    • 問題來了,前者認為 C 是強型別,後者認為 C 是弱型別,衝突了
    • “強弱型別” 有兩種截然不同分類觀點:
      • 從數據類型轉換和語法角度
      • 編譯和運行中操作不同角度
  • Ref:
    • http://ot-note.logdown.com/posts/173174/note-cpp-named-type-convertion
    • http://www.jianshu.com/p/336f19772046
    • https://www.zhihu.com/question/19918532
    • https://www.zhihu.com/question/19918532/answer/23217475
    • http://linianhui.cnblogs.com/p/plp_04_datatypes.html
    • https://stackoverflow.com/questions/17202208/typed-vs-strongly-typed-in-c-sharp https://dotblogs.com.tw/justforgood/2015/04/09/151000
    • http://javapig.pixnet.net/blog/post/48216506-c%23--%E4%BD%95%E8%AC%82%E5%BC%B7%E5%9E%8B%E5%88%A5
    • http://a7419.pixnet.net/blog/post/88870641-c%23%E5%9E%8B%E5%88%A5%E8%BD%89%E6%8F%9B

2017年7月28日 星期五

[C#] Custom column using Dapper (3)

  • Dapper.FluentColumnMapping

  • 安裝中發生錯誤
    • .Net Framework 4.5 版本不支援 
    • 查看官網資訊(Dependencies: .NETFramework 4.5.1, Dapper (>= 1.42.0))
    • 需要將 .Net Framework 4.5 變更為 .NETFramework 4.5.1
    • 如 Dapper.1.50.2 版本,將會發生 Warring 

  • Sql 資料
  • -- =============================================
    -- Author:  Lyndonliu
    -- =============================================
    ALTER PROCEDURE [dbo].[SP_DemoGetUserInfo]
    
    AS
    BEGIN
     SELECT 
     UserInfo.Name AS '姓名',
     UserInfo.Age AS '年齡'
     FROM UserInfo
    END
    
  • 資料結構 
    • Code
    namespace CustomColumnLibrary.Models
    {
        /// 
        /// User Info
        /// 
        public class User
        {
            /// 
            /// User Name
            /// 
            [Column(Name = "姓名")]
            public string Name { get; set; }
            /// 
            /// User Age
            /// 
            [Column(Name = "年齡")]
            public int Age { get; set; }
        }
    }
    
  • Dapper 查詢
    • Code
    
                    List< User> lUser = null;
                    using (SqlConnection con = new SqlConnection(Info.LyndonliuConnectionString))
                    {
                        // 欄位對應
                        ColumnMappingCollection columnMappings = new ColumnMappingCollection();
    
                        columnMappings.RegisterType< User>()
                                      .MapProperty(x => x.Name).ToColumn("姓名")
                                      .MapProperty(x => x.Age).ToColumn("年齡");
    
                        columnMappings.RegisterWithDapper();
    
                         // 執行 Query
                        lUser = con.Query< User>("SP_DemoGetUserInfo",
                                            commandType: CommandType.StoredProcedure,
                                            commandTimeout: 0).ToList();
                    }
    
  • 此方法最不推薦,因需修改 .Net Framework 4.5.1 與所支援的  Dapper 為舊版本
  • Ref
    • https://dotblogs.com.tw/supershowwei/2016/08/16/175753

[C#] Custom column using Dapper (2)


  • 引用 Dapper.FluentMap
  • Sql 資料
  • 
    -- =============================================
    -- Author:  Lyndonliu
    -- =============================================
    ALTER PROCEDURE [dbo].[SP_DemoGetUserInfo]
    
    AS
    BEGIN
     SELECT 
     UserInfo.Name AS '姓名',
     UserInfo.Age AS '年齡'
     FROM UserInfo
    END
    

  • 資料結構 User
    • Code
    
    namespace CustomColumn2ndLibrary.Models
    {
        /// 
        /// User Info
        /// 
        public class User
        {
            /// 
            /// User Name
            /// 
            public string Name { get; set; }
            /// 
            /// User Age
            /// 
            public int Age { get; set; }
        }
    }
  • 實作一個繼承自 EntityMap<T> 類別
    • Code
    
    using Dapper.FluentMap.Mapping;
    
    namespace CustomColumn2ndLibrary.Models
    {
        public class UserMap : EntityMap< User>
        {
            public UserMap()
            {
                // ToColumn() 方法中
                // caseSensitive 參數設為 false,可以呼略欄位名稱的大小寫
                Map(x => x.Name).ToColumn("姓名");
                Map(x => x.Age).ToColumn("年齡");
            }
        }
    }
    
  • Dapper 查詢
    • Code
    
                    List< User> lUser = null;
                    using (SqlConnection con = new SqlConnection(Info.LyndonliuConnectionString))
                    {
                        // 初始化 Map
                        FluentMapper.Initialize(cfg =>
                        {
                            cfg.AddMap(new UserMap());
                        });
    
                         // 執行 Query
                        lUser = con.Query< User>("SP_DemoGetUserInfo",
                                            commandType: CommandType.StoredProcedure,
                                            commandTimeout: 0).ToList();
                    }
    
  • Ref:
    • https://dotblogs.com.tw/supershowwei/2016/08/16/175753

2017年7月27日 星期四

[C#] Custom column using Dapper (1)


  • 主要有時後回傳 Column 的名稱,不好閱讀或者是中文,因此想要重新命名,但通常需要修改 SQL 語法,如不想修改 SQL 語法,可使用此方法
  • 實作 SqlMapper.ITypeMap
  • 將 ColumnAttributeTypeMapper.cs 實作至專案中
  • Sql 資料
  • 
    -- =============================================
    -- Author:  Lyndonliu
    -- =============================================
    ALTER PROCEDURE [dbo].[SP_DemoGetUserInfo]
    AS
    BEGIN
        SELECT 
        UserInfo.Name AS '姓名',
        UserInfo.Age AS '年齡'
        FROM UserInfo
    END
    

  • 資料結構 member 
    • Add [Column(Name = "ColumnName")] info
    • Code
    
    using CustomColumnLibrary.Infrastructure;
    
    namespace CustomColumnLibrary.Models
    {
        /// 
        /// User Info
        /// 
        public class User
        {
            /// 
            /// User Name
            /// 
            [Column(Name = "姓名")]
            public string Name { get; set; }
            /// 
            /// User Age
            /// 
            [Column(Name = "年齡")]
            public int Age { get; set; }
        }
    }
    
  • Dapper 查詢
    • Add Dapper.SqlMapper.SetTypeMap Info
    • Code
    
                    List< User> lUser = null;
                    using (SqlConnection con = new SqlConnection(Info.LyndonliuConnectionString))
                    {
                        // 呼叫 Dapper.SqlMapper.SetTypeMap
                        // 對應的類別跟欄位映射丟進去就可以了
                        Dapper.SqlMapper.SetTypeMap(typeof(User), new ColumnAttributeTypeMapper< User>());
    
                        // 執行 Query
                        lUser = con.Query< User>("SP_DemoGetUserInfo",
                                            commandType: CommandType.StoredProcedure,
                                            commandTimeout: 0).ToList();
                    }

2017年7月26日 星期三

[MVC] Json keys are lowercase on MVC API


  • Pascal 命名格式
    • Code
    
    using System.ComponentModel.DataAnnotations;
    
    namespace WebAPIDemo.Models
    {
        /// 
        /// User Data
        /// 
        public class User
        {
            /// 
            /// User Name
            /// 
            public string Name { get; set; }
            /// 
            /// User Age
            ///    
            public int Age { get; set; }
        }
    }
    
    • 但所取得 JSON 格式為 Class member 的結果,因此第一字為大寫

  • Json lowercase
    • 使用 Json.Net
    • Code
    
    using System.ComponentModel.DataAnnotations;
    using Newtonsoft.Json;
    
    namespace WebAPIDemo.Models
    {
        /// 
        /// User Data
        /// 
        public class User
        {
            /// 
            /// User Name
            /// 
            [JsonProperty(PropertyName = "name")]
            public string Name { get; set; }
            /// 
            /// User Age
            /// 
            [JsonProperty(PropertyName = "age")]        
            public int Age { get; set; }
        }
    }
    
    • Psotmen: 輸出結果為 PropertyName 所命名的結果 

  • Ref:
    • http://kevintsengtw.blogspot.tw/2016/02/aspnet-web-api-import-postman.html

2017年7月25日 星期二

[MVC] Create API and Help page on MVC 5

  • 選擇 Web API
  • 關閉 AD 驗證
  • 基礎的範本程式碼
  • 步驟1: 手動加入 XML 文件檔案
    • 此步驟會幫助,程式中所撰寫的 <summary> 資訊代入 Help Page
    • 查尋 HelpPageComfig.cs 中修改資訊

    • Before Code: 開始是被註解起來

        public static void Register(HttpConfiguration config)
        {
            //// Uncomment the following to use the documentation from XML documentation file.
            //config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));
            ... 
        }
    • After Code: 解註解並修改對應的 XML 路徑

        public static void Register(HttpConfiguration config)
        {
            //// Uncomment the following to use the documentation from XML documentation file.
            config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));
            ... 
        }
  • 實作 Get / Post
    • Class Code
    namespace WebAPIDemo.Models
    {
        /// 
        /// User Data
        /// 
        public class User
        {
            /// 
            /// User Name
            /// 
            public string Name { get; set; }
            /// 
            /// User Age
            /// 
            public int Age { get; set; }
        }
    }
    
    • Get / Post API 
    
    using System.Web.Http;
    using WebAPIDemo.Models;
    
    namespace WebAPIDemo.Controllers
    {
        /// 
        /// How to using Web API
        /// 
        public class DemoController : ApiController
        {
            /// 
            /// Get User Info
            /// 
            ///  User Info 
            public User Get()
            {
                User user = new User()
                {
                    Name = "Lyndon",
                    Age = 30
                };
    
                return user;
            }
    
            /// 
            /// Add User Age
            /// 
            ///  User Info 
            public User Post(User Info)
            {
                Info.Age = Info.Age + 10;
    
                return Info;
            }
        }
    }
    
    • Postmen Get
    • Postmen Post: 需要傳入參數
    • Help Info 
      • <summary> 所寫入的資訊都會出現在 Help 中

  • POST 有些參數必輸入資訊,需進行下列修改
    • Code
    
    using System.ComponentModel.DataAnnotations;
    
    namespace WebAPIDemo.Models
    {
        /// 
        /// User Data
        /// 
        public class User
        {
            /// 
            /// User Name
            /// 
            [Required]
            [StringLength(10, ErrorMessage = "請勿輸入超過10個字")]
            public string Name { get; set; }
            /// 
            /// User Age
            /// 
            public int Age { get; set; }
        }
    }
    
    • Help: 加入條件說明
    • POST API Code
      
              /// 
              /// Add User Age
              /// 
              ///  User Info 
              public User Post(User Info)
              {
                  if (ModelState.IsValid)
                  {
                      // Do something with the user (not shown).
                      //return new HttpResponseMessage(HttpStatusCode.OK);
                      Info.Age = Info.Age + 10;
                      return Info;
                  }
                  else
                  {
                      //return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
                      return null;
                  }
              }
      
    • Postmen
  • Ref
    • http://kevintsengtw.blogspot.tw/2015/12/aspnet-web-api-help-page.html
    • https://stackoverflow.com/questions/26098077/microsoft-web-api-help-page-how-to-create-annotations-for-parameters
    • https://docs.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api
    • http://kevintsengtw.blogspot.tw/2016/02/aspnet-web-api-import-postman.html



2017年7月24日 星期一

[C#] Object Initializers, Collection Initializers

  • 由於 Auto-implemented properties 的用法產生,也連同產生出新的 Object Initializers, Collection Initializers
    • Code
    
        public class User
        {
            // Auto-implemented properties.
            public string Name { get; set; }
            public int Age { get; set; }
        }
  • Object Initializers
    • Code
      • 一般用法
        public class Initializers
        {       
            public void function()
            {
                User user = new User();
                user.Name = "Lyndon";
                user.Age = 30;
            }
        }
    • Code
      • syntactic sugar 語言特性來簡化
    
        public class Initializers
        {       
            public void function()
            {
                User user = new User() { Name = "Lyndon", Age = 30 };
            }
        }
    
  • Collection Initializers
    • Code 2.0
    
        public class Initializers
        {       
            public void function()
            {
                List< User> lUser = new List< User>();
                lUser.Add( new User { Name = "Helen", Age = 25 } );
                lUser.Add( new User { Name = "Lyndon", Age = 30 } );
                lUser.Add( new User { Name = "Daisy", Age = 27 } );
            }
        }
    
    • Code 3.0 (Orcas version)
    
    public class Initializers
        {       
            public void function()
            {
                List< User> lUser = new List< User>()
                {
                    new User { Name = "Helen", Age = 25 },
                    new User { Name = "Lyndon", Age = 30 },
                    new User { Name = "Daisy", Age = 27 }
                };
            }
        }
    
        public class Initializers
        {       
            public void function()
            {
                Dictionary< int, User> students = new Dictionary< int, User>()
                {
                    { 111, new User { Name = "Helen", Age = 25 }},
                    { 112, new User { Name = "Lyndon", Age = 30 }},
                    { 113, new User { Name = "Daisy", Age = 27 }}
                };
            }
        }
    • Code 3.0 固定記憶體大小
      • 一般陣列宣告後,會給固定的記憶體大小
    
        public class Initializers
        {       
            public void function()
            {
                List< User> lUser = new List< User>(3)
                {
                    new User { Name = "Helen", Age = 25 },
                    new User { Name = "Lyndon", Age = 30 },
                    new User { Name = "Daisy", Age = 27 }
                };
            }
        }
  • Ref
    • https://weblogs.asp.net/scottgu/new-c-orcas-language-features-automatic-properties-object-initializers-and-collection-initializers
    • https://docs.microsoft.com/zh-tw/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers
    • https://docs.microsoft.com/zh-tw/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers

2017年7月23日 星期日

[C#] Auto-implemented Properties History


  • Characteristic
    • 封裝,資料保護及隱藏
  • .NET Framework 1.0
    • Code
    
        public class AutomaticProperties
        {
            private string _Name;
    
            public string getName()
            {
                return _Name;
            }
    
            public void setName(string arg)
            {
                _Name = arg;
            }
    
            private int _Age;
    
            public int getAge()
            {
                return _Age;
            }
    
            public void setAge(int arg)
            {
                _Age = arg;
            }
        }
    
  • .NET Framework 2.0
    • Code snippets (propfull)
    • Code
    
    public class AutomaticProperties
        {
            private string _Name;
    
            public string Name
            {
                get
                {
                    return _Name;
                }
                set
                {
                    _Name = value;
                }
            }
    
            private int _Age;
    
            public int Age
            {
                get
                {
                    return _Age;
                }
                set
                {
                    _Age = value;
                }
            }
        }
    
  • .NET Framework 3.0 ~ 5.0
    • Code snippets (prop)
    • Code
    
        public class AutomaticProperties
        {
            public string Name
            {
                get;
                set;
            }
    
            public int Age
            {
                get;
                set;
            }
        }
    
    • Code 進一步縮減
    
        public class AutomaticProperties
        {
            public string Name { get; set; }
    
            public int Age { get; set; }
        }
    
    • Code 唯讀
      • 建構值中初始化
    
        public class AutomaticProperties
        {
            public AutomaticProperties()
            {
                Name = "Lyndon";
                Age = 30;
            }
    
            public string Name { get; private set; }
    
            public int Age { get; private set; }
        }
    
    • Code 唯讀,進一步縮減
      • 因不是標記成 abstract 或 extern,因此必須宣告主體
    
        public class AutomaticProperties
        {
            /// 
            /// 直接回傳值
            /// 
            public string Name
            {
                get
                {
                    return "Lyndon";
                }
            }
    
            public int Age
            {
                get
                {
                    return 30;
                }
            }
        }
    
  • .NET Framework 6.0
    • Code
    
        public class AutomaticProperties
        {
            public string Name { get; } = "Lyndon";  
    
            public int Age { get; set; } = 30;
        }
  • Ref:
    • http://blog.xuite.net/sunnysoap/r/65597736
    • http://blog.csdn.net/heqi915/article/details/1589777
    • http://alansong.pixnet.net/blog/post/55999534-c%23-get-set-%E5%8F%8A%E8%87%AA%E5%8B%95%E5%B1%AC%E6%80%A7
    • https://docs.microsoft.com/zh-tw/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties

2017年7月22日 星期六

[C#]NuGet - Dapper(Insert, Select, StoredProcedure, Multiple table)

  • 概要
    • 因許多人有介紹如何安裝與細節,在此就不在多介紹
    • 下列的範例 Code 為各項操作,主要 Data Class 如下
    
        public class User
        {
            /// 
            /// Name
            /// 
            public string Name { get; set; }
            /// 
            /// Age
            /// 
            public int Age { get; set; }
        }
    • Database 
  • CommandType
    • CommandType.Text for an SQL text command. (Default.)
    • CommandType.StoredProcedure for the name of a stored procedure.
    • CommandType.TableDirect for the name of a table. (不支援)
  • Dapper INSERT
    • Code - one data
    
                    int count = 0;
                    using (SqlConnection con = new SqlConnection(Info.LyndonliuConnectionString))
                    {
                        User user = new User();
                        user.Name = "Helen";
                        user.Age = 25;
    
                        //1) 可執行SQL資料更新指令,支援參數
                        var Param = new DynamicParameters();
                        Param.Add("@Name", user.Name, dbType: DbType.String);
                        Param.Add("@Age", user.Age, dbType: DbType.Int32);
    
                        count = con.Execute(
                            "INSERT INTO UserInfo VALUES (@Name, @Age)",
                            Param,
                            commandTimeout: 0);
                    }
    
    • Code - Multiple data
    
                    int count = 0;
                    using (SqlConnection con = new SqlConnection(Info.LyndonliuConnectionString))
                    {
                        //2) 以陣列方式提供多組參數,可重複執行同一SQL指令
                        //   它可以一次傳進多組參數,用不同參數重複執行同一SQL操作,批次作業時格外有用
                        //   指定的型別(屬性與欄位名稱要一致)
                        List< User> lUser = new List< User>()
                        {
                            new User(){ Name = "Lyndon", Age = 30 },
                            new User(){ Name = "Daisy", Age = 27 },
                        };
    
                        count = con.Execute(
                            "INSERT INTO UserInfo VALUES (@Name, @Age)",
                            lUser,
                            commandTimeout: 0);
                    }
    
  • Dapper SELECT
    • Code - one data
    
                    List< User> lUser = null;
                    using (SqlConnection con = new SqlConnection(Info.LyndonliuConnectionString))
                    {
                        //1) 將SELECT結果轉成指定的型別(屬性與欄位名稱要一致)
                        lUser = con.Query< User>(
                            "SELECT * FROM UserInfo",
                            commandTimeout: 0).ToList();
                    }
    
    • Code - Where 
    
                    List< User> lUser = null;
                    using (SqlConnection con = new SqlConnection(Info.LyndonliuConnectionString))
                    {
                        //2) 可執行SQL資料更新指令,支援參數
                        var Param = new DynamicParameters();
                        Param.Add("@Age", 26, dbType: DbType.Int32);
    
                        lUser = con.Query< User>(
                            "SELECT * FROM UserInfo WHERE Age > @Age",
                            Param,
                            commandTimeout: 0).ToList();
                    }
    
    • Code - Where In
    
                    List< user> lUser = null;
                    using (SqlConnection con = new SqlConnection(Info.LyndonliuConnectionString))
                    {
                        //3) 直接傳數字陣列作為WHERE IN比對參數
                        //   =>自動轉成WHERE col in (@arg1,@arg2,@arg3)
                        lUser = con.Query< user>(
                            "SELECT * FROM UserInfo WHERE Age IN @Age",
                            new { Age = new int[] { 25, 30 } },
                            commandTimeout: 0).ToList();
                    }
    
  • Dapper StoredProcedure
    • Code - StoredProcedure (one table)
    
    USE [MVCVISTA]
    GO
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    -- =============================================
    -- Author:  Lyndonliu
    -- =============================================
    ALTER PROCEDURE [dbo].[SP_DemoGetUserInfo]
    
    AS
    BEGIN
     SELECT * FROM UserInfo
    END
    
    
    
                    List< User> lUser = null;
                    using (SqlConnection con = new SqlConnection(Info.LyndonliuConnectionString))
                    {
                        //1) 將SELECT結果轉成指定的型別(屬性與欄位名稱要一致)
                        lUser = con.Query< User>(
                            "SP_DemoGetUserInfo",
                            commandType: CommandType.StoredProcedure,
                            commandTimeout: 0).ToList();
                    }
    
    • Code - StoredProcedure (one table where)
    
    USE [MVCVISTA]
    GO
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    -- =============================================
    -- Author:  Lyndonliu
    -- =============================================
    ALTER PROCEDURE [dbo].[SP_DemoGetUserInfo](
     @Age int
    )
    
    AS
    BEGIN
     SELECT * FROM UserInfo WHERE Age > @Age
    END
    
    
                    List< User> lUser = null;
                    using (SqlConnection con = new SqlConnection(Info.LyndonliuConnectionString))
                    {
                        //2) 可執行SQL資料更新指令,支援參數
                        var Param = new DynamicParameters();
                        Param.Add("@Age", 27, dbType: DbType.Int32);
    
                        lUser = con.Query< User>(
                            "SP_DemoGetUserInfo",
                            Param,
                            commandType: CommandType.StoredProcedure,
                            commandTimeout: 0).ToList();
                    }
    
    • Code - StoredProcedure (multiple table)
    
    USE [MVCVISTA]
    GO
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    -- =============================================
    -- Author:  Lyndonliu
    -- =============================================
    ALTER PROCEDURE [dbo].[SP_DemoGetUserInfo](
     @Age int
    )
    
    AS
    BEGIN
     SELECT MAX(Age) AS MAXAge FROM UserInfo
     SELECT MIN(Age) AS MINAge FROM UserInfo
     SELECT * FROM UserInfo WHERE Age > @Age
    END
    
    
                    int MAXAge = 0;
                    int MINAge = 0;
                    List< User> lUser = null;
                    using (SqlConnection con = new SqlConnection(Info.LyndonliuConnectionString))
                    {
                        //2) 可執行SQL資料更新指令,支援參數
                        var Param = new DynamicParameters();
                        Param.Add("@Age", 27, dbType: DbType.Int32);
    
                        //3) 可回傳多個 table 
                        //   接收順序有先後問題,順序不正確將接收錯誤的資訊
                        using (var multi = con.QueryMultiple("SP_DemoGetUserInfo",
                                                            Param,
                                                            commandType: CommandType.StoredProcedure,
                                                            commandTimeout: 0))
                        {
                            MAXAge = multi.Read< int>().FirstOrDefault();
                            MINAge = multi.Read< int>().FirstOrDefault();
                            lUser = multi.Read< User>().ToList();
                        }
                    }
  • Ref:
    • http://blog.darkthread.net/post-2014-05-15-dapper.aspx
    • http://stackoverflow.com/questions/16993021/how-to-insert-null-values-to-a-uniqueidentifier-column
    • https://stackoverflow.com/questions/14191278/what-is-the-purpose-of-using-commandtype-tabledirect
    • http://stackoverflow.com/questions/7836766/calling-a-stored-procedure-with-asp-net
    • http://stackoverflow.com/questions/5962117/is-there-a-way-to-call-a-stored-procedure-with-dapper
    • http://stackoverflow.com/questions/6387904/how-to-insert-an-ienumerablet-collection-with-dapper-dot-net
    • http://stackoverflow.com/questions/17150542/how-to-insert-a-c-sharp-list-to-database-using-dapper-net
    • https://www.jeremymorgan.com/blog/programming/how-to-dapper-web-api/
    • https://stackoverflow.com/questions/6751052/how-to-map-multiple-records-from-a-single-sp-with-dapper-dot-net

2017年7月21日 星期五

[MVC] API to Return XML


  • Solution 
    • If you return a serializable object, WebAPI will automatically send JSON or XML based on the Accept header that your client sends.
  • Code
    /// 
    /// Demo API
    /// 
    public class DemoController : ApiController
    {
        public class User
        {
            /// 
            /// User Name
            /// 
            public string Name { get; set; }
            /// 
            /// User age
            /// 
            public int Age { get; set; }
        }

        /// 
        /// Get User list
        /// 
        ///  User list 
        public List< User> Post()
        {
            // Get user list
            List< User> lUser = new List< User>()
            {
                new User(){ Name = "Lyndon", Age = 30 },
                new User(){ Name = "Daisy", Age = 27 },
            };

            return lUser;
        }
    }
  • JSON
    • Harders 不需加入任何參數
  • XML
    • Harders 加入 Accept: application/xml
  • Ref:
    • https://stackoverflow.com/questions/11662028/webapi-to-return-xml

[MVC] Access-Control-Allow-Origin Issue


  • Question
    • Access-Control-Allow-Origin
    • A網頁使用 jquery ajax 呼叫B API,產生下列圖示的錯誤

    • 但使用 Postman 呼叫,卻是一切正常
  • Solution
    • 需要在 Header 輸入 Access-Control-Allow-Origin 的資訊
    • 但簡單的方式在 B API 專案的 Web.config,進行修改
    • Code 原本
    
    < configuration>
      < system.webServer>
      ...
      < /system.webServer>
    < /configuration>
    • Code 加入
    
    < configuration>
      < system.webServer>
          ... 
          < httpProtocol>
            < customHeaders>
              < clear/>
              < add name="Access-Control-Allow-Origin" value="*"/>
            < /customHeaders>
          < /httpProtocol>
      < /system.webServer>
    < /configuration>
  • Ref
    • http://www.c-sharpcorner.com/blogs/how-to-enable-cross-origin-resource-sharing-in-mvc1

2017年7月20日 星期四

[C#] Value Types, Reference Types, Pointers


  • C# 有兩種資料型別:
    • 實值(Value Types)和參考(Reference Types)
    • 如果應用程式的效能很重要,或是如果您對 C# 如何管理資料和記憶體有興趣,了解兩者之間的差別就很重要。
  • Value Type
    • 繼承自 System.ValueType
    • 儲存的值是「實值」(Value)
    • 當變數是以基本內建資料型別其中之一,或使用者定義的結構進行宣告時
      • bool
      • byte
      • char
      • decimal
      • double
      • enum
      • float
      • int
      • long
      • sbyte
      • short
      • struct
      • ...
    • 將內容儲存在配置於堆疊 (Stack) 的記憶體中
    
    int x = 42;
    • 當變數 x 因為所定義的方法完成執行而超出範圍時,堆疊就會捨棄此值。
    • 使用堆疊很有效率,但是實值型別有限的存留期,使其較不適合在不同類別之間共用資料
  • Reference Types
    • 不是繼承自 System.ValueType 的型別,都不是 Value Type
    • 儲存的值是「參考」(Reference),也就是記憶體的位址,指向儲存真實內容的記憶體區塊的開始位置
    • 參考型別 (例如類別或陣列的執行個體) 
      • class
      • interface
      • delegate
      • object
      • string
    • 配置在稱為堆積 (Heap) 的不同記憶體區域中
    
    int[] numbers = new int[10];
    • 當方法完成時,這段記憶體不會歸還給堆積,只有當 C# 的記憶體回收系統判定不再需要它時才會回收。在宣告參考型別時需要較大的額外負荷,但是它們有可以從其他類別存取的優點
    • 需要GC(Garbage collection:垃圾收集器)清理
  • Value Type and Reference Type 
    • 記憶體用途分為 Stack 與 Heap 兩種
    • 最顯著的差別,記憶體中儲存其變數值的方式
    • 所有的區域變數 (不管是 Value Type 或是 Reference Type),其內容 (變數名稱、型別與與值) 都是儲存在 Stack 中
    • new 關鍵字實體化類別的物件,其物件內容,是儲存在 Heap 中
    • Reference Type 變數中所儲存的參考,其實是指向 Heap 中的記憶體位址
    • 由於 Value Type 與 Reference Type 在記憶體儲存值上的差異,在使用上若不理解,有時會造成意料外的問題
  • Pointer Type
    • 主要是 C/C++ 語言,對記憶體直接操作
    • 在內存區中,指向一個類型的引用,通常被稱為 Pointer Type
    • 它是受CLR (Common Language Runtime:公共語言運行時) 管理,我們不能顯示使用
    • 需要註意,一個類型的引用即 Pointer Type 跟 Reference Type 是完全不同概念
    • Pointer Type 在內存中占一塊內存區,它本身代表一個內存地址 (或者null),它所指向的另一塊內存區才是我們真正的數據或者類型
  • Ref:
    • https://msdn.microsoft.com/zh-tw/library/4d43ts61(v=vs.90).aspx
    • http://xingulin.tumblr.com/post/48493582986/ref-type-vs-val-type
    • http://www.c-sharpcorner.com/article/C-Sharp-heaping-vs-stacking-in-net-part-i/
    • https://www.codeproject.com/Articles/76153/Six-important-NET-concepts-Stack-heap-value-types
    • http://www.15jb.net/article/43475.html
    • http://m.jb51.net/article/55306.htm

2017年7月19日 星期三

[MVC] MVC 5 API on IIS 7, Windows 2008 (Fix HTTP ERROR 403.14)


  • Question
    • 開發環境
      • VS2013 - MVC 5 API
    • 架設環境
      • Win 7, IIS 7.5 - 成功
      • Win 2008, IIS 7 - 失敗
  • Error - HTTP ERROR 403.14 

    • 修改
      • Code
      
        < system.webServer >
          < modules runAllManagedModulesForAllRequests="true" >
            < remove name="FormsAuthentication" >
          < /modules >
          ...
        < /system.webServer >
      

  • REF: 
    • https://blog.miniasp.com/post/2013/06/24/ASPNET-MVC-4-IIS-runAllManagedModulesForAllRequests-ExtensionlessUrlHandler.aspx
    • http://blog.darkthread.net/post-2015-05-30-aspnet-mvc-on-win2008.aspx
    • http://www.luminowebdesign.no/tech-blogg/asp-net-routing-and-web-config-setting-runallmanagedmodulesforallrequests

2017年7月18日 星期二

[C#]Struct, Class


  • struct

    1. 成員預設是 public
    2. 值類型,struct 不能設 null
      • Code
      • struct AStruct
        {
           int aField;
        }
        
        class MainClass
        {
            public static void Main()
            {
                AStruct s = null; // Error [ Cannot convert null to 'AStruct' because it is a value type ].
            }
        }
    3. 創建在 stack (由編譯器分配內存空間的,調用構造函數來構造 stack 對象)
    4. 不是對 struct 的引用 (直接使用它們)
    5. struct 傳遞的市值而非引用
    6. struct 不可以有初始化
      • Code
      • struct MyStruct
        {   
            int myVar = 10;  //  syntax error. 
            public void MyFun() 
            {       
                //  statements    
            }
        }
        
    7. struct 不可以有明顯的無參數構造器
      • Code
      • struct MyStruct
        { 
            int myVar;
            public MyStruct() // syntax error.
            {      
                // statements 
            }
        }
        
    8. struct 不需要實例化
      • Code
      • MyStruct aStructObj;
        /// 
        /// no exception
        /// 
        aStructObj.myVar=100;
        
    9. struct 不支持繼承和多型,注意:但是 struct 可以像 class 實現接口 (其成員不能使用 protected 或 protected Internal )
    10. struct 構造器必須初始化所有字段
      • Code
      • /// 
        /// Error 
        /// Field 'MyStruct.myString' must be fully assigned before it leaves the constructor
        /// 
        struct MyStruct
        { 
            int myInt;  
            string myString; 
            public MyStruct( int aInt ) 
            {    
                myInt = aInt;  
            }
        }
        
    11. struct 不可以定義析構器
    12. struct 適用於經常使用的數據組合成的新類型

  • class

    1. 成員預設是 private
    2. 引用類型,class 可以設定為 null
      • Code
      • class  AClass
        {
           int aField;
        }
        
        class MainClass
        {
            public static void Main()
            {
                AClass b = null; // No error.
            }
        }
        
    3. 創建在 heap (建立在 heap,類對象只能建立在 ,不能是靜態建立對象,且不濘接條用類得構造函數)
    4. class 實例的引用
    5. class 作為參數傳給一個方法,傳遞的是一個引用
    6. class 可以有初始化
      • Code
      • class MyClass
        {  
            int myVar =10;  //  no syntax error.    
            public void MyFun()
            {       
                //  statements    
            }
        }
        
    7. class 可以有明顯的無參數構造器
      • Code
      • class MyClass
        {  
            int myVar = 10;
            public MyClass() // no syntax error. 
            {   
                // statements
            }
        } 
    8. class 使用前必須 new 關鍵字實例化
      • Code
      • /// 
        /// MyClass aClassObj=new MyClass(); is the correct format.aClassObj.
        /// 
        MyClass aClassObj;
        /// 
        /// NullReferenceException
        /// (because aClassObj does not contain a reference to an object of type myClass).
        /// 
        aClassObj.myVar = 100; 
        
    9. class 支持繼承和多型
    10. class 構造器不需要初始化所有字段
      • Code
      • /// 
        /// No error
        /// No matter whether the Field 'MyClass.myString' is initialized or not
        /// 
        class MyClass
        { 
            int myInt;  
            string myString;   
            public MyClass( int aInt )
            {    
                myInt = aInt;    
            }
        }
        
    11. class 可以定義析構器
    12. class 適合大的量和複雜的數據

  • struct and class


  • struct 有性能優勢,class 有面向對象的擴展優勢。用於底層數據存儲的類型設計爲struct 類型,將用於定義應用程式列爲的類型設計爲 class。如果對類型將來的應用情況不能確定,應該使用 class。
  • Ref: 
  • http://jashliao.pixnet.net/blog/post/207253459-c%23-%E4%B8%AD-struct-%E8%88%87-class-%E7%9A%84%E5%8D%80%E5%88%A5%EF%BC%8C%E4%BB%A5%E5%8F%8A%E5%85%A9%E8%80%85%E7%9A%84%E9%81%A9%E7%94%A8%E5%A0%B4
  • http://www.cnblogs.com/waitrabbit/archive/2008/05/18/1202064.html
  • https://docs.microsoft.com/zh-tw/dotnet/csharp/programming-guide/classes-and-structs/using-structs 
  • https://read01.com/3RQD6K.html
  • http://www.cnblogs.com/liuzijing688/archive/2008/01/11/1034893.html
  • http://weisnote.blogspot.tw/2012/08/static.html

  • 2017年7月17日 星期一

    [C#]const, static readonly


    • const
      • 編譯期間就確定
      • 因此只能宣告通過常量表達式來指定值
    • static readonly
      • 宣告時可不強制初始值,但宣告 readonly 之後不能再給值,所以一般宣告 static readonly 時一定會給初始值,不過其初始值是可變
      • 運行時計算的值,所以可以通過靜態結構函數來賦值
      • Reference類型,只是被限定不能進行賦值(寫入)操作。其它成員的讀寫仍然是不受限制
        • Code
          
          public static readonly MyClass myins = new MyClass();
          /// 
          /// 正常
          /// 
          myins.SomeProperty = 10;
          /// 
          /// 錯誤,該物件只能讀取
          /// 
          myins = new MyClass();
      • 如上中的 MyClass 不是 class 而是 struct,後面的兩個語句都會出錯
    • const and static readonly
      • 唯讀變數
      • 系統啟動時就存在,其生命週期等同Application變數
        • Code
        
        /// 
        /// 1.不可以換成 const,new 超作需要執行建構函数,所以無法在編譯期間確定
        /// 
        static readonly MyClass myins = new MyClass();
        /// 
        /// 2.不可以換成 const,理由跟 1 一樣,雖然 1,2,3 的數組是一個常量
        /// 
        static readonly int [] constIntArray = new int[] {1, 2, 3};
        /// 
        /// 3.可以換成 const,Reference 類型的常量(除了String)只能是 Null
        /// 
        static readonly MyClass myins = null;
        /// 
        /// 3.可以換成 const,可在編譯期間很明確,A等於200
        /// 
        static readonly A = B * 20;
        static readonly B = 10;
        /// 
        /// 5.不可以換成 readonly,readonly 只能用來修飾類 field,不能修飾局部變量,也不能修飾 property 等其它類成員
        /// 
        void SomeFunction()
        {
            const int a = 10;
        }
      • 對於那些本質上應該是常量,但是卻無法使用const來聲明的地方,可以使用static readonly
        • Code
        
        public class Color
        {
            public static readonly Color Black = new Color(0, 0, 0);
            public static readonly Color White = new Color(255, 255, 255);
            public static readonly Color Red = new Color(255, 0, 0);
            public static readonly Color Green = new Color(0, 255, 0);
            public static readonly Color Blue = new Color(0, 0, 255);
        
            private byte red, green, blue;
        
            public Color(byte r, byte g, byte b)
            {
                red = r;
                green = g;
                blue = b;
            }
        }
    • const and static readonly different 1
      • static readonly
        • Code
        
        using System;
        class Demo
        {
            static readonly int A = B * 10;
            static readonly int B = 10;   
            public static void Main(string[] args)
            {
                Console.WriteLine("A is {0},B is {1} ", A, B);
            }
        }
        • 輸出結果是 A is 0, B is 10
      • const
        • Code
        
        using System;
        class Demo
        {
            const int A = B * 10;
            const int B = 10;   
            public static void Main(string[] args)
            {
                Console.WriteLine("A is {0},B is {1} ", A, B);
            }
        }
        • 輸出結果是 A is 100, B is 10
      • const 是靜態常量,所以在編譯時候就將 A 與 B 的值確定 ( B 值為 10,而 A = B * 10 為 100 ) ,因此輸出當然為 A is 100, B is 10
      • static readonly 為動態常量,變量值在編譯期間不予解析,所以開始都是默認值,因 A 與 B 都是 int 類型,初始值為 0。而程序執行到 A = B * 10; 所以 A = 0 * 10 為 0,程序接著執行到 B = 10 時候,才會真正初始 B 的值,將 10 賦給 B
    • const and static readonly different 2
      • static readonly
        • Code
        
        /// 
        /// 正確:初始值是可變
        /// 
        static readonly int delayMonth = DateTime.Now.Month;
        

      • const
        • Code
        
        /// 
        /// 正確
        /// 
        const int delayMonth = 1;
        /// 
        /// 錯誤:因為 DateTime.Now. 是可變,如:本月是7,但下個月是8,常數必須是明確固定值,而不是隨著外在因素變動 
        /// 
        const int delayMonth = DateTime.Now.Month;
      • 兩個特性作比較,switch 陳述式必須不可變動值才能作 case 動作,所以 static readonly 並不適用,只能使用 const 變數
    • REF
      • http://www.cnblogs.com/wangshenhe/archive/2012/05/16/2503831.html
      • https://dotblogs.com.tw/kim/2009/05/11/const
      • https://msdn.microsoft.com/zh-tw/library/aa645753(v=vs.71).aspx

    2017年7月16日 星期日

    [C#] Object-oriented programming


    • OOP (Object-oriented programming)
      • Class - 類別
      • Object - 物件
      • Encapsulation - 封裝
      • Inheritance - 繼承
      • Polymorphism - 多型
      • Abstraction - 抽象
    • Class 類別
      • 定義了一件事物的抽象特點
      • 類別的定義包含了資料的形式以及對資料的操作
      • 一個類別的方法和屬性被稱為"成員"
      • Code

    • Object - 物件
      • 物件有時會對應到現實世界中的事物
      • 程式在物件導向編程當中被視為方法,變數被視為成員或屬性
      • Code

    • Encapsulation 封裝
      • 一特定類別的成員,利用介面實作訊息的傳入傳出
      • 通常來說,成員會依它們的存取權限被分為:
        • public
        • private
        • protected
        • internal
        • protected internal
      • Code

    • Inheritance 繼承
      • 在某種情況下,一個類別會有"子類別"
      • 子類別比原本的類別(稱為父類別)要更加具體化
      • 子類別會繼承父類別的屬性和行為,並且也可包含它們自己
      • 這意味著程式設計師只需要將相同的代碼寫一次
      • Code

    • Polymorphism 多型
      • 繼承而產生的相關的不同的類別,其物件對同一訊息會做出不同的回應
      • Code

    • Ref:
      • https://zh.wikipedia.org/wiki/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1
      • https://dotblogs.com.tw/ace_dream/tags/1?qq=OOP

    2017年7月15日 星期六

    [C#]interface and abstract class


    • Info

      • General
      • Abstracts
        • 為了實現"多型"精神
      • Interface
        • 介面可以同時"繼承"多個介面

    • General Class

      • UML
      • Code
          /// 
          /// General Class
          /// 
          public class GeneralClass
          {
              public string Number { get; set; }
              public void ShowNumber()
              {
                  System.Console.WriteLine(string.Format("Your number is {0}", Number));
              }
      
              /// 
              /// Abstracts method 只能定義在 Abstracts class
              /// 
              //public abstract string absName { get; set; }
              //public abstract void absShowName();
      
              public virtual string virYear { get; set; }
              public virtual void virShowYear()
              {
                  System.Console.WriteLine(string.Format("You are {0} years old", virYear));
              }
          }
      
      • Implementation Code
      
          /// 
          /// Implementation General Class
          /// 
          public class GenImplementationClass : GeneralClass
          {
              /// 
              /// 1. 在繼承一般類別時,一般的方法不可以被覆寫
              /// 
              // public override void ShowNumber() { }
      
              /// 
              /// 2. 可以用 new 修飾詞來隱藏父類別中的這個方法
              /// 
              public new void ShowNumber()
              {
                  System.Console.WriteLine(string.Format("Your house number is {0}", Number));
              }
      
              /// 
              /// 3. 父類別中的 virtual mothed 才可以被覆寫
              /// 
              public override void virShowYear() 
              {
                  System.Console.WriteLine(string.Format("This year is {0}", virYear));
              }
          }
      

    • Abstracts Class

      • 定義
        • 宣告類別時,使用 abstract 修飾詞
        • abstract 類別只能被繼承,不能直接使用 new 語法建立實體
      • UML
      • Code
          /// 
          /// Characteristic
          /// I.Abstracts class
          ///     1.Abstracts class 不能 new 去產生物件
          ///     2.Abstracts class 一定要繼承後,才能使用到它內部的功能
          ///     3.Abstracts class 定義了 Abstracts method ,繼承它的子類別一定要實作這個 method
          ///     4.Abstracts class 沒有要求所有成員都要是抽象的
          ///         但是若 class 中有任何一個 Abstracts 成員,則該 class 必須為 Abstracts class 
          /// II.Abstracts method 
          ///     1.Abstracts method 只需要宣告, 不需要實作
          ///     1.Abstracts method 只能定義在 Abstracts class
          ///     2.Abstracts method 不能使用 private 存取修飾詞
          ///     3.繼承 Abstracts class 子類別必須實作父類別的 Abstracts method, 否則這子類別還是個 Abstracts class
          /// 
          public abstract class AbstractsClass
          {
              /// 
              /// general method
              /// 
              public string Number { get; set; }
      
              public void ShowNumber() 
              {
                  System.Console.WriteLine(string.Format("Your number is {0}", Number));
              }
              /// 
              /// abstract method: 必須在子類別中被實作
              /// 
              public abstract string absName { get; set; }
      
              public abstract void absShowName();
              /// 
              /// virtual method: 允許在子類別中被覆寫
              /// 
              public virtual string virYear { get; set; }
              public virtual void virShowYear()
              {
                  System.Console.WriteLine(string.Format("You are {0} years old", virYear));
              }
          }
      
      • Implementation Code
          /// 
          /// override: 宣告這個方法是覆寫父類別中的 Abstracts method 或 virtual method
          /// 
          public class AbsImplementationClass : AbstractsClass
          {
              /// 
              /// 可以用 new 修飾詞來隱藏父類別中的這個方法,
              /// 
              public new void ShowNumber()
              {
                  System.Console.WriteLine(string.Format("Your house number is {0}", Number));
              }
      
              /// 
              /// 繼承 Abstracts class, 一定要實作它的 Abstracts metho, 同樣是以覆寫的方式來做.
              ///         public override string absName { get; set; }
      
              public override void absShowName()
              {
                  System.Console.WriteLine(string.Format("Your name is {0}", absName));
              }
      
              /// 
              /// override: 覆寫父類別中的 virtual method
              ///         
              public override string virYear { get; set; }
      
              public override void virShowYear() 
              {
                  System.Console.WriteLine(string.Format("This year is {0}", virYear));
              }
          }
      

    • Interface Class

      • 定義
        • 可模擬多重繼承,一個類別可同時實作多個介面
        • 使用 inferface 關鍵字宣告,命名習慣最前面加上 I 
        • 僅可定義抽象成員 (不支援 Field,可支援 Property, Method)
          • 不須實作
          • 皆為 public
      • UML
      • Code
          /// 
          /// Characteristic
          /// I. Interface
          ///     1.interface 沒有建構方法 (即 method 中沒有參數, 且沒有任何變數的設定)
          ///     2.類別中僅定義 member 名稱,沒有內容
          ///     3.實作這個 Interface method,必需支援該 Interface 的所有 member
          ///     4.介面可包含方法、屬性、事件、索引子,不能包含常數、欄位、運算子、執行個體建構函式
          ///     5.介面裡的 method 必須全部都定義成 public abstract
          ///     6.method 的預設修飾詞就是使用 public abstract ,所以可以省略
          ///         public abstract interface InterfaceClass >>> interface InterfaceClass
          /// 
          interface InterfaceClass
          {
              string Number { get; set; }
              void ShowNumber();
              string Name { get; set; }
              void ShowName();
              string Year { get; set; }
              void ShowYear();
          }
      
      • Implementation Code
          /// 
          /// 當使用類別的繼承功能時,一次只能繼承一個類別,可以當實作介面時,一次可以實作多個介面
          /// 
          public class IntImplementationClass : InterfaceClass
          {
              /// 
              /// 支援該介面的所有成員
              /// 
              public string Number { get; set; }
      
              public void ShowNumber()
              {
                  System.Console.WriteLine(string.Format("Your house number is {0}", Number));
              }
      
              public string Name { get; set; }
      
              public void ShowName()
              {
                  System.Console.WriteLine(string.Format("Your name is {0}", Name));
              }
      
              public string Year { get; set; }
      
              public void ShowYear() 
              {
                  System.Console.WriteLine(string.Format("This year is {0}", Year));
              }
          }
      
    • Ref:
      • http://jimmu-jimmu.blogspot.tw/2012/10/abstract-classinterface.html
      • http://vito-note.blogspot.tw/2014/08/blog-post_65.html
      • https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/keywords/abstract