2010年9月1日 星期三

工具分享:Smart Paster

在Visual Studio中寫程式,有時候會遇到需要Copy/Paste大量字串的時候,
例如:SQL Statement、HTML、文章…etc
這時候有些人就會發揮阿信的精神,一行一行的複製然後貼上,
而有些人則是會先將需要的部分複製到VS中,然後再一行一行的去處理這些文字。
而到了VS中,處理字串的連接就又是一們學問,有人喜歡直接用「 += 」的方式來串接(相當不建議)

例如:
string sqlStatement1 = string.Empty;
 
sqlStatement1 += "SELECT *";
sqlStatement1 += "FROM dbo.Categories INNER JOIN";
sqlStatement1 += "  dbo.Products INNER JOIN";
sqlStatement1 += "  dbo.Orders INNER JOIN";
sqlStatement1 += "  dbo.[Order Details Extended] ON dbo.Orders.OrderID = dbo.[Order Details Extended].OrderID ON dbo.Products.ProductID = dbo.[Order Details Extended].ProductID ON ";
sqlStatement1 += "Details Extended].ProductID ON ";
sqlStatement1 += "  dbo.Categories.CategoryID = dbo.Products.CategoryID";
sqlStatement1 += "WHERE";
sqlStatement1 += "    (dbo.Orders.OrderDate BETWEEN '19970101' AND '19971231')";
sqlStatement1 += "GROUP BY ";
sqlStatement1 += "    dbo.Categories.CategoryID, dbo.Categories.CategoryName, dbo.Products.ProductName";

我想這是一般最常看到的情況,字串是個靜態的型別,當你用 += 去接字串的同時,+= 的後面也都是多去產生一個string型別物件,

如果有使用for迴圈的方式去接這樣的字串,那就是會產生n個字串物件,對於記憶體與效能上是不太好的,

最重要的是,大量的字串 Copy/Paste 蠻浪費時間的。


另外有人會建議使用 StringBuilder 來處理這樣的字串,當然是建議使用 StringBuilder 來處理,
但是對於這樣繁複的 Copy/Paste 動作是有必要去簡化的,偷懶是進步與效能增進、詩間減少的最大原動力(?!)

其實我一直使用一個VS的Add-in,「Smart Paster」來做為這樣情況下的一個撇步。

在程式區塊中,按下滑鼠右鍵,選單最上方有個「Paste As …」(這是我有裝 Add-in 才會有這個,沒裝的人不要在那邊找老半天)

image

選擇用StringBuilder的方式,它會幫我們處理成以下的內容,
StringBuilder sb = new StringBuilder(471);
sb.AppendLine(@"SELECT *");
sb.AppendLine(@"FROM dbo.Categories INNER JOIN");
sb.AppendLine(@"  dbo.Products INNER JOIN");
sb.AppendLine(@"  dbo.Orders INNER JOIN");
sb.AppendLine(@"  dbo.[Order Details Extended] ON dbo.Orders.OrderID = dbo.[Order Details Extended].OrderID ON dbo.Products.ProductID = dbo.[Order Details Extended].ProductID ON ");
sb.AppendLine(@"  dbo.Categories.CategoryID = dbo.Products.CategoryID");
sb.AppendLine(@"WHERE");
sb.AppendLine(@"\t(dbo.Orders.OrderDate BETWEEN '19970101' AND '19971231')");
sb.AppendLine(@"GROUP BY ");
sb.AppendLine(@"\tdbo.Categories.CategoryID, dbo.Categories.CategoryName, dbo.Products.ProductName");

只要一個動作,就可以做完,除了就是使用 StringBuilder 來幫你處理串接,

另外也幫你再每行前面加上 @,讓你可以不處理escape。


再看看,如果是用 Comment(註解模式)
//SELECT *
//FROM dbo.Categories INNER JOIN
//  dbo.Products INNER JOIN
//  dbo.Orders INNER JOIN
//  dbo.[Order Details Extended] ON dbo.Orders.OrderID = dbo.[Order Details Extended].OrderID ON dbo.Products.ProductID = dbo.[Order Details Extended].ProductID ON 
//  dbo.Categories.CategoryID = dbo.Products.CategoryID
//WHERE
//    (dbo.Orders.OrderDate BETWEEN '19970101' AND '19971231')
//GROUP BY 
//    dbo.Categories.CategoryID, dbo.Categories.CategoryName, dbo.Products.ProductName


最後看看一般的 String 模式,就是幫你處理成一個字串內容,沒有分行、分段。
@"SELECT *
FROM dbo.Categories INNER JOIN
dbo.Products INNER JOIN
dbo.Orders INNER JOIN
dbo.[Order Details Extended] ON dbo.Orders.OrderID = dbo.[Order Details Extended].OrderID ON dbo.Products.ProductID = dbo.[Order Details Extended].ProductID ON 
dbo.Categories.CategoryID = dbo.Products.CategoryID
WHERE
(dbo.Orders.OrderDate BETWEEN '19970101' AND '19971231')
GROUP BY 
dbo.Categories.CategoryID, dbo.Categories.CategoryName, dbo.Products.ProductName"

這樣的工具一開始是由Alex Papadimoulis所製作,以下是他的Blog中對Smart Paster的介紹

http://weblogs.asp.net/alex_papadimoulis/archive/2004/05/25/Smart-Paster-1.1-Add-In---StringBuilder-and-Better-C_2300_-Handling.aspx

image

在此文章中,他提供了 VS2003, VS2005, VS2008的支援

image



而當VS2010 Release之後,就沒看到作者釋出鄉對應的支援版本,不過還是有人依據原作者所提供的Source而做了出來

http://martinwilley.com/blog/2010/06/06/SmartPasteIn2010.aspx

image


Add-in的安裝相當簡單,就是將下載後的壓縮檔,把裡面的檔案複製到Visual Studio位於USER電腦中的Document的目錄。


SmartPaster2008

image

複製到 (.\Documents\Visual Studio 2008\Addins)

image



SmartPaster2010

image

複製到 (.\Documents\Visual Studio 2010\Addins)

image


以上的動作完成後,記得重新啟動你的Visual Stuidio。

安裝完成並且重新啟動VS後,就可以使用了…

不過VS2010的版本好像沒有提供設定的功能,在原作者的版本中則是有提供這樣的設定功能。


in VS2008
image


設定功能

image

可以讓你自由設定你所喜好的樣式,

在VS2008的版本中還可以讓你去設定每個分行段落,是不是要用Environment.NewLine等

image


相關連結
Alex Papadimoulis' .NET Blog - Smart Paster 1.1 Add-In - StringBuilder and Better C# Handling
Static Void - Smart Paste in 2010

以上





2 則留言:

  1. I have a question.

    What is the different between

    StringBuilder sb = new StringBuilder(471);

    sb.AppendLine(@"SELECT *");

    sb.AppendLine(@"FROM dbo.Categories INNER JOIN");

    and

    string sql = @"SELECT *
    FROM dbo.Categories INNER JOIN ";
    (Note: There are two lines here. )

    回覆刪除
  2. Hello Maxisam,i answered in Madrain...

    Using the StringBuilder Class
    http://msdn.microsoft.com/en-us/library/2839d5h5(v=vs.90).aspx

    使用StringBuilder去組合字串不會讓系統去一直建立新的String物件,
    使用一般的 string 串接字串則會一直新建立String物件,

    而StringBuilder可以在建立物件時去指定它的最大容量、長度,
    而當容量滿了之後,就會再動態增加一樣的容量,

    基本上你所提出的兩個比對,有什麼不同?......是沒有什麼不同,
    而有差異的地方在於,用StringBuilder的AppenbdLine()方法,可以讓輸入的字串呈現有換行的內容格式,
    相對的直接使用String將所有的SQL Command輸入,則只會單純呈現單一行的格式,
    而你在字串前面有加上@的話,所輸出的內容就會保持換行的內容格式。

    所以你所提出的兩者比較,兩者的輸出結果是相同的。
    至於為何要用StringBuilder,
    如果是固定以及可知長度的文字內容要做串接動作,其實可以直接使用String+= "....."; 的方式,
    那要是不確定長度且內容並非固定的文字內容(如動態產生),
    這時候會比較建議使用StringBuilder來做字串的串接動作。

    回覆刪除

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。