GooglePrettify

2018年8月17日 星期五

How to handle Task.Run Exception

var task = Task.Run(...)

try
{
    task.Wait(30000); // Rethrows any exception(s).
    ...

reference : https://stackoverflow.com/questions/32067034/how-to-handle-task-run-exception

2018年7月1日 星期日

C# 筆記:擴充方法

摘要:本文將簡單介紹 C# 3.0 的新語法:擴充方法(extension methods)。

典型場景

經常開發 .NET 應用程式的人,相信多少都會建立一套自己專屬的類別庫,畢竟作為通用目的 .NET Framework 不可能滿足所有應用程式的需求。比如說,自己開發的類別庫可能也會提供字串工具類別、日期時間、檔案 I/O、資料處理等工具類別。就拿字串處理來說好了,.NET 的 String 類別沒有提供字串反轉的方法,如果我們要在自己的字串工具類別中提供這個方法,可能會這麼寫:

程式列表 1:StringExtension 類別
   1:  public static class StringExtension
   2:  {
   3:      // 字串反轉
   4:      public static string Reverse(string s)
   5:      {
   6:          if (String.IsNullOrEmpty(s))
   7:              return "";
   8:          char[] charArray = new char[s.Length];
   9:          int len = s.Length - 1;
  10:          for (int i = 0; i <= len; i++)
  11:          {
  12:              charArray[i] = s[len - i];
  13:          }
  14:          return new string(charArray);
  15:      }
  16:  }
由於 StringExtension 只是單純提供字串處理的工具類別,它並不需要保存什麼狀態資料,因此我們它宣告為靜態類別。靜態類別無法建立 instance,而且只能包含靜態方法,所以我們的 Reverse 方法也是宣告為 static。
於是,我們在應用程式中便可以這麼寫:
程式列表 2:呼叫 StringExtension 類別的靜態方法
   1:  class Program
   2:  {
   3:      static void Main(string[] args)
   4:      {
   5:          string s = "123456789";
   6:          Console.WriteLine(StringExtension.Reverse(s));        
   7:      }
   8:  }
OK! 到這裡為止都是我們非常熟悉的寫法。接著進入正題:擴充方法。

改用擴充方法

試想一下,如果「程式列表 2」的第 6 行在處理字串反轉時可以這麼寫:

   6:          Console.WriteLine(s.Reverse());        
如何?看起來是不是好像 String 類別原本就有提供 Reverse 方法?不僅如此,原本的 Reverse 是靜態方法,現在卻使用 instance method 的方式呼叫了。是的,這就是 extension methods 所要達成的效果。
如果你覺得這種寫法還不賴,接著就來看看 StringExtension 類別的 Reverse 方法要如何修改才能讓它(看起來)成為 String 類別的一份子。很簡單,只要將「程式列表 1」的第 4 行改成這樣就行了:

   4:      public static string Reverse(this string s)
這裡的神奇關鍵字是:this。當你在靜態方法的參數列中加入關鍵字 this ,它就變成了擴充方法,而你就可以在程式中使用 instance methods 的方式呼叫此方法。當然,原本的靜態方法的呼叫方式也還是可以用。
可是,編譯器怎麼知道我要擴充的是 String 類別呢?答案是:編譯器會將關鍵字 this 後面接著的型別視為該方法所欲擴充的類別
再舉一個例子。假設我們有一個處理日期時間的工具類別,其中有一個 ToRocDateString 方法,程式碼如下:

程式列表 3:DateTimeExt 類別
   1:  public static class DateTimeExt
   2:  {
   3:      // 將 DateTime 物件格式化成中華民國年份的日期字串.
   4:      public static string ToRocDateString(DateTime date, char separator)
   5:      {
   6:          int year = (date.Year - 1911);
   7:          return year.ToString() + separator + date.Month + separator + date.Day;
   8:      }
   9:  }
ToRocDateString 方法的用途是將傳入的 DateTime 物件格式化成中華民國年份的日期字串,它需要兩個參數,一個是 DateTime 物件,另一個是日期分隔字元。現在,如果要讓它成為 DateTime 類別的擴充方法,就只要在第 4 行的第一個參數前面加上 this:

   4:      public static string ToRocDateString(this DateTime date, char separator)
這引出了擴充方法的另一項規則:欲擴充的類別必須放在參數列的第一個位置。也就是說,關鍵字 this 只能用在第一個參數型別。如果你將 this 加在第二個或後面的參數,程式將無法通過編譯。
在使用 ToRocDateString 擴充方法時,只需要傳入一個參數,像這樣:

Console.WriteLine(DateTime.Now.ToRocDate('/'));
你不用擔心呼叫擴充方法時會忘記要傳入哪些參數,Visual Studuo 的 IntelliSense 功能會提示你。

結語

擴充方法並沒有增加 .NET runtime 的負擔,一切都是由編譯器幫我們搞定--編譯器會到程式引用的各個 namespaces 中搜尋符合條件的擴充方法。如果你用 ILDASM 或 Reflector 工具去看編譯出來的 IL code,你就會看到,呼叫擴充方法的程式碼其實還是編譯成靜態方法呼叫。
雖然它很方便(想像一下如果你要擴充的是 System.Object 類別!),但還是要注意避免濫用,如果用得太多,可能就會發生擴充方法名稱衝突的情形。此外,對於不是使用 Visual Studio 來寫程式的人來說,那些擴充方法呼叫可能會讓他們挺傷腦筋的吧!
Happy coding :)

from : https://www.huanlintalk.com/2009/01/csharp-3-extension-methods.html

2018年6月29日 星期五

How to rename a Project Folder from within Visual Studio?

My current solution for renaming the project folder is:
  • Remove the project from the solution.
  • Rename the folder outside Visual Studio.
  • Re-add the project to the solution.

from : https://stackoverflow.com/questions/211241/how-to-rename-a-project-folder-from-within-visual-studio

2018年6月7日 星期四

How to access ICollection index

ProductDTO product = ((IList<ProductDTO>)Products)[0];

from : https://stackoverflow.com/questions/1875655/why-icollection-index-does-not-work-when-instantiated

2018年6月5日 星期二

InvalidOperationException exception (cannot be serialized because it does not have a parameterless constructor)

Serialization enables us to store or transmit data structures or objects. This can be done by converting the data to a textual representation when storing or transmitting them which also allows us to recreate the original object using the stored information.
Lets create a dummy class called Person, that will hold some basic information.
Keep in mind that your class needs to have a parameterless constructor in order to be serialized or else you will get an InvalidOperationException exception (cannot be serialized because it does not have a parameterless constructor) if you try to serialize a class without one. Luckily you can just set it to private or internal so it won’t be accessible from other classes.
Now it is time to serialize our Person object.

At this point our serializedData variable will be holding the serialized data. This is what you will use when storing or transmitting your object somewhere. You can see below the contents of serializedData.
Now lets deserialize our data to recreate our Person object.
The deserializedPerson object will have exactly the same data as the object we serialized at the start.
Hopefully the above example helped you understand the basics on how to serialize and deserialize objects. If you have any questions feel free to ask in the comments below.

from : https://www.fluxbytes.com/csharp/serialize-an-object-to-string-and-from-string-back-to-object/