星期三, 10月 29, 2014

[Win] 陰影複製

紀錄 Windows Server 2012 R2 的陰影複製設定

陰影複製說明:
  • 存取舊版本資料和救回刪除檔案
  • 可以排程定期追蹤磁碟上的檔案異動
  • 不能用來取代備份
圖一:陰影複製是針對磁碟進行設定,選定目標磁碟

圖二:按下啟用按鈕

圖三:陰影複製注意事項,不適合 I / O 負載較高的伺服器

圖四:啟用後會馬上進行陰影複製,也有 "立即建立" 按鈕,可以手動建立

圖五:圖二中的設定按鈕,可以指定陰影複製存放位置和最大容量

圖六:圖五中的排程按鈕,預設排程一天兩次,分別為 0700 am 和 1200 pm

圖七:啟動陰影複製前,已在 C 磁碟中建立 ShadowDemo 資料夾,資料夾中有檔案 1、檔案 2 兩檔案,為了測試陰影備份,對檔案 1 內容進行修改並刪除檔案 2

針對檔案 1 可以在內容的 "以前的版本" 看見可用備份

已刪除的檔案 2,因為沒有檔案存在,可以在資料夾中的 "以前的板本" 中,把檔案 2 救回來,還原會回復整個資料夾,複製可以把整個資料夾還原到指定位置

檔案 1 和 檔案 2 就救回來啦

星期二, 10月 28, 2014

[C#] TreeView for WebForm

利用組織圖來練習 ASP.NET TreeView 控件,主要是應用 SQL Server CTE 語法組成名稱路徑配合 ValuePath 屬性來完成 TreeView
  • SQL Server 資料建立
原始資料截圖

[C#] TreeView-1

星期一, 10月 27, 2014

[C#] DataGridView 中顯示圖片

論壇問題
如何在datagridview 中讓使用者自行放入圖片?
using System.IO;

namespace GridImage
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 建立資料來源
            DataTable dt = new DataTable("Demo");
            dt.Columns.Add("ID", typeof(int));
            dt.Columns.Add("FileName", typeof(string));
            dt.Columns.Add("Photo", typeof(Image));

            // image00.jpg 內容是"未上傳"字樣
            dt.Rows.Add("1", "",Image.FromFile(@"D:\image00.jpg"));
            dt.Rows.Add("2", "",Image.FromFile(@"D:\image00.jpg"));
            dt.Rows.Add("3", "",Image.FromFile(@"D:\image00.jpg"));
            dt.Rows.Add("4", "",Image.FromFile(@"D:\image00.jpg"));
            dt.Rows.Add("5", "",Image.FromFile(@"D:\image00.jpg"));
            dgvData.DataSource = dt;

            // DataGridView 基礎設定
            dgvData.AllowUserToAddRows = false;
            dgvData.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

            // 設定 DataGridViewImageColumn 圖片寬度
            dgvData.Columns["ColImage"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

            // 設定 DataGridViewButtonColumn Text 屬性
            DataGridViewButtonColumn btncol = dgvData.Columns["ColUpload"] as DataGridViewButtonColumn;
            if (btncol != null)
            {
                // 表示全部 Button 的 Text 都顯示 "選擇圖片" 
                btncol.UseColumnTextForButtonValue = true;
                btncol.Text = "選擇圖片";
            }
        }

        private bool ImageCheck(string photopath)
        {
            // 判斷該圖檔是否存在
            if (File.Exists(photopath) == false) return false;
            // 只接受 JPG 圖檔
            if (Path.GetExtension(photopath).ToUpperInvariant() != ".JPG") return false;
            return true;
        }

        private void setImage()
        {
            OpenFileDialog OFD = new OpenFileDialog();
            OFD.FileName = "請選取圖檔";
            if (OFD.ShowDialog() != DialogResult.OK || string.IsNullOrEmpty(OFD.FileName)) return;
            string photopath = OFD.FileName;
            if (ImageCheck(photopath) == false) return;
            dgvData.CurrentRow.Cells["ColFileName"].Value = photopath;
            dgvData.CurrentRow.Cells["ColImage"].Value = Image.FromFile(photopath);
        }

        private void dgvData_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            // 判斷是不是 DataGridViewButtonColumn 欄位
            if (e.ColumnIndex == dgvData.Columns["colUpload"].Index) setImage();
        }
    }
}
[C#] DataGridView 中顯示圖片

星期五, 10月 24, 2014

[Azure] SSMS 連線 SQL Database

第一次接觸 Azure,看著大神的教學 - 用 SQL Server Management Studio 連線 Windows Azure 上的 SQL Database ,想說用 SSMS 來連接 SQL Database 並不是甚麼困難的事情,沒想到還是花費不少時間才成功 ~~ >.<

Azure => SQL 資料庫 => SQL2014(事先建好的 SQL Database)

[Azure] SSMS 連線 SQL Database-1

SQL2014 => 儀表板

[Azure] SSMS 連線 SQL Database-2

儀錶板頁面又下角可以看見該 Database 相關資料,SSMS 要利用下圖中的 "伺服器名稱" 來連接 SQL2014,"管理 URL" 是另外一段故事,後面紀錄,>.<

[Azure] SSMS 連線 SQL Database-3

第一次使用 Azure 情況下,要先設定允許的 IP 位置,下圖畫面在儀表板內右下角可以找到

[Azure] SSMS 連線 SQL Database-4

畫面上會顯示 Client 端 IP 位置,只要按下加入即可

[Azure] SSMS 連線 SQL Database-5

輸入伺服器名稱、選擇 SQL Server 驗證並輸入建立 SQL Database 時的登入帳號和密碼

[Azure] SSMS 連線 SQL Database-6

在 SSMS 中登錄 SQL Database 成功,可以看見 instance 圖示右下角會有一個淺藍色圖示

[Azure] SSMS 連線 SQL Database-7

 登錄過程中發生的小狀況
  • 大神影片中是抓取 "管理 URL" (可以從伺服器資料那張圖中看見)資料,然後把它 copy 到 SSMS 中並刪除後面的 SQL Database 名稱,我沒有注意到不需要 https 字樣,一直用 https:ServaerName.database.windows.net 去連接,一直都失敗,嘗試過 Azure 提供的連接字串用 SSMS 或寫 C# 進行連接都 OK,後來才從連接字串中發現到只要輸入 ServerName.database.windows.net 就好 ~~ 暈 ~~
  • 第一次使用 Azure,不知道要設定允許 IP,連接時才發現下列的錯誤訊息 ~~
[Azure] SSMS 連線 SQL Database-8

星期四, 10月 23, 2014

[C#] FileUpload 多選

FileUpload 多選練習
  • dotNet 4.5:FileUpload AllowMultiple屬性 
  • dotNet 4.5 前版本:Panel 內有多個 FileUpload 控件
using System.IO;

namespace MultiUpload
{
    public partial class _default : System.Web.UI.Page
    {
        string serverPath = @"D:\FileUploadDemo";
        string serverFilePath = string.Empty;

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                // 設定該屬性 FileUpload 就具有多選檔案功能
                FU1.AllowMultiple = true;
            }
        }

        protected void btnUpload_Click(object sender, EventArgs e)
        {
            if (FU1.HasFiles == false) return;

            foreach (HttpPostedFile file in FU1.PostedFiles)
            {
                serverFilePath = Path.Combine(serverPath, file.FileName);
                try
                {
                    // 網友發現該錯誤
                    // FU1.SaveAs(serverFilePath);
                    file.SaveAs(serverFilePath);
                    lblMessage.Text = "上傳成功";
                }
                catch (Exception ex)
                {
                    lblMessage.Text = ex.Message;
                }
            }
        }

        protected void btnPanelUpload_Click(object sender, EventArgs e)
        {
            // 搜尋 Panel 內的 FileUpload 控件
            foreach (FileUpload fu in plFU.Controls.OfType<fileupload>())
            {
                // 判斷有哪些 FileUpload 有選擇檔案
                if (fu.HasFile == false) continue;
                serverFilePath = Path.Combine(serverPath, fu.FileName);
                try
                {
                    fu.SaveAs(serverFilePath);
                    lblPanelMessage.Text = "上傳成功";
                }
                catch (Exception ex)
                {
                    lblPanelMessage.Text = ex.Message;
                }
            }
        }
    }
}
[C#] FileUpload 多選

星期一, 10月 20, 2014

[C#] 格式化 DataGridView 內資料

練習在 DataGridView 內,對資料進行格式化
  1. Money 欄位資料每三位有ㄧ個小數點
  2. Money 欄位內不同金額區間設定不同顏色表示
  3. 點選 Money 欄位內資料,會改變顏色來強化點選的 cell
  4. 日期欄位內資料指定格式化為 D
  5. NULL 值必須顯示未輸入日期字樣
  6. Money 欄位利用 CellFomatting、Date 欄位利用 DefaultCellStyle.Format 來格式化
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 建立基礎資料
            DataTable dt = new DataTable("Demo");
            dt.Columns.Add("ID", typeof(int));
            dt.Columns.Add("Money", typeof(decimal));
            dt.Columns.Add("Date", typeof(DateTime));
            dt.Rows.Add(1, 2456, DateTime.Now);
            dt.Rows.Add(2, 789456123, DateTime.Now.AddDays(1));
            dt.Rows.Add(3, 456123, DateTime.Now.AddDays(2));
            dt.Rows.Add(4, 1, DateTime.Now.AddDays(3));
            dt.Rows.Add(5, 1111, null);
            dt.Constraints.Add("PK", dt.Columns["ID"], true);
            dgvData.DataSource = dt;
            dgvData.AllowUserToAddRows = false;

            // 利用 DefaultCellStyle.Format 屬性來 Date 欄位格式化
            dgvData.Columns["Date"].DefaultCellStyle.Format = "d";
            dgvData.Columns["Date"].DefaultCellStyle.NullValue = "未輸入日期";
        }

        private void dgvData_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            // 利用 CellFormatting 來完成 Money 欄位格式化
            if (dgvData.Columns[e.ColumnIndex].Name.Equals("Money"))
            {

                decimal money = (decimal)e.Value;

                e.CellStyle.Format = "###,###,###";
                e.CellStyle.SelectionBackColor = Color.Red;
                e.CellStyle.SelectionForeColor = Color.White;
                e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;

                if (money > 0 && money <= 1000) e.CellStyle.BackColor = Color.LightBlue;
                if (money > 1000 && money <= 10000) e.CellStyle.BackColor = Color.LightGreen;
                if (money > 10000) e.CellStyle.BackColor = Color.LightPink;
            }
        }
    }
}
[C#] 格式化 DataGridView 內資料

星期五, 10月 17, 2014

[C#] FileUpload 上傳檔案

FileUpload 控件練習,筆記重點為
  • 判斷是否為允許上傳的檔案附檔名
  • 限制檔案大小,限制為 2MB
  • 判斷 Server 上檔案名稱是否有重覆情況,有的話必須進行更名
using System.IO;

namespace UploadSample
{
    public partial class _default : System.Web.UI.Page
    {
        protected void btnUpload_Click(object sender, EventArgs e)
        {

            if (FU1.HasFile == false) return;

            // FU1.FileName 只有 "檔案名稱.附檔名",並沒有 Client 端的完整理路徑
            string filename = FU1.FileName;

            string extension = Path.GetExtension(filename).ToLowerInvariant();
            // 判斷是否為允許上傳的檔案附檔名
            List<string> allowedExtextsion = new List<string> { ".jpg", ".bmp" };
            if (allowedExtextsion.IndexOf(extension) == -1)
            {
                lblMessage.Text = "不允許該檔案上傳";
                return;
            }

            // 限制檔案大小,限制為 2MB
            int filesize = FU1.PostedFile.ContentLength;
            if (filesize > 2100000)
            {
                lblMessage.Text = "檔案大小上限為 2MB,該檔案無法上傳";
                return;
            }

            // 檢查 Server 上該資料夾是否存在,不存在就自動建立
            string serverDir = @"D:\FileUploadDemo";
            if (Directory.Exists(serverDir) == false) Directory.CreateDirectory(serverDir);

            // 判斷 Server 上檔案名稱是否有重覆情況,有的話必須進行更名
            // 使用 Path.Combine 來集合路徑的優點
            //  以前發生過儲存 Table 內的是 \\ServerName\Dir(最後面沒有 \ 符號),
            //  直接跟 FileName 來進行結合,會變成 \\ServerName\DirFileName 的情況,
            //  資料夾路徑的最後面有沒有 \ 符號變成還需要判斷,但用 Path.Combine 來結合的話,
            //  資料夾路徑沒有 \ 符號,會自動補上,有的話,就直接結合
            string serverFilePath = Path.Combine(serverDir, filename);
            string fileNameOnly = Path.GetFileNameWithoutExtension(filename);
            int fileCount = 1;
            while (File.Exists(serverFilePath))
            {
                // 重覆檔案的命名規則為 檔名_1、檔名_2 以此類推
                filename = string.Concat(fileNameOnly,"_",fileCount,extension);
                serverFilePath = Path.Combine(serverDir, filename);
                fileCount++;
            }

            // 把檔案傳入指定的 Server 內路徑
            try
            {
                FU1.SaveAs(serverFilePath);
                lblMessage.Text = "檔案上傳成功";
            }
            catch (Exception ex)
            {
                lblMessage.Text = ex.Message;
            }
        }
    }
}
  • 控件畫面:FileUpload + Buton + Label 三個控件而已 ~~
[C#] FileUpload 上傳檔案

星期四, 10月 16, 2014

[Excel] 快速填入 & 資料分析

利用下面資料來紀錄快速填入和資料分析兩個功能的使用方式
  • 原始資料
[Excel] 快速填入 & 資料分析-1

星期三, 10月 15, 2014

[C#] How do you check if a number is a power of 2?

MVA Twenty C# Questions Explained - [07 ​How do you check if a number is a power of 2?]

很特別的主題
namespace MVATwentyQuestions
{
    class Program
    {
        static void Main(string[] args)
        {
            bool result = false;
            result = CheckPowerOfTwo(8);
            Console.WriteLine(result.ToString());
        }

        static bool CheckPowerOfTwo(ulong number)
        {
            return (number != 0) && ((number & (number - 1)) == 0);
        }

    }
}

星期二, 10月 14, 2014

[C#] DateTimePicker

紀錄一下 DateTimePicker 基本操作
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 設定 dtp 日期格式
            dtp.Format = DateTimePickerFormat.Custom;
            dtp.CustomFormat = "yyyy/MM/dd";
   
            // 設定 dtpTime 顯示時間,tt 代表 上午/下午
            dtpTime.Format = DateTimePickerFormat.Custom;
            dtpTime.CustomFormat = "tt hh:mm";
            dtpTime.ShowUpDown = true;

            // 設定 dtpLimit 限制日期區間,今日的前後一週
            dtpLimit.MaxDate = DateTime.Today.AddDays(7);
            dtpLimit.MinDate = DateTime.Today.AddDays(-7);
        }

        private void btnsettime_Click(object sender, EventArgs e)
        {
            // 設定一周後的日期
            dtp.Value = DateTime.Today.AddDays(7);
        }

        private void dtp_ValueChanged(object sender, EventArgs e)
        {
            // Text 回傳 string 
            txtDate.Text = dtp.Text;

            // Value 回傳 datetime,且可以利用日期相關功能來抓取個別資訊
            txtYear.Text = dtp.Value.Year.ToString();
            txtMonth.Text = dtp.Value.Month.ToString();
            txtDay.Text = dtp.Value.Day.ToString();
        }
    }
}
[C#] DateTimePicker 基本操作

星期一, 10月 13, 2014

風扇

製造廠內空壓機是少不了的設備,因此在維護電腦時,常常會利用空壓機來吹灰塵,但因為空壓機的風壓很強,常常會讓風扇瞬間轉很快,我自己處理時都會把風扇固定住,才進行吹灰塵的動作,避免風扇產生問題

但這次不是我去維護,悲劇就真的發生啦,而且還是直接把葉片吹斷(下圖箭頭處),太誇張了啦 ~~

風扇

星期五, 10月 10, 2014

[VFP] ADODB.Connection: 找不到提供者。它可能未被正確安裝

程式發生下列錯誤訊息
程式發生異常,錯誤訊息如下:
使用者:OOXX
電腦:QCUSER-PC # QCUser
發生時間:03/10/02 01:28:36 PM
錯誤行數:294
錯誤程式碼: OLE IDispatch 異常碼 0 出自 ADODB.Connection: 找不到提供者。它可能未被正確安裝。。.
錯誤訊息:OLE IDispatch 異常碼 0 出自 ADODB.Connection: 找不到提供者。它可能未被正確安裝。。.
錯誤程式觸發: DATATOEXCEL
錯誤編號:1429
ODBC訊息:找不到提供者。它可能未被正確安裝。
ODBC SQL 狀態:ADODB.Connection
ODBC 資料來源錯誤編號:C:\Windows\HELP\ADO270.CHM
ODBC 連接控制碼:1240655
ㄧ看見這個錯誤訊息,直覺就是該電腦並沒有安裝 Microsoft Access Database Engine 2010 可轉散發套件(以下簡稱 Microsof ACE.OLEDB.12.0),安裝完就離開,連測試都沒有測試,沒想到使用者還是回報說有相同的錯誤訊息,慘 ~~

測試後發現到問題,該 OS 是 64 bit,所以直覺是安裝 64 bit Microsof ACE.OLEDB.12.0,但沒想到 Office 2013 是 32 bit 的,暈
  • Win7 64 bit
[VFP] ADODB.Connection 找不到提供者。它可能未被正確安裝-1
  • Office 2013 32 bit
[VFP] ADODB.Connection 找不到提供者。它可能未被正確安裝-2

[VFP] ADODB.Connection 找不到提供者。它可能未被正確安裝-3

重新安裝 32 bit Microsof ACE.OLEDB.12.0 就解決這個問題 ~~

星期四, 10月 09, 2014

[Win] Windows Server 2012 R2 上安裝 dotNet 3.5

在 Windows Server 2012 R2 上安裝 dotNet 3.5,原以為角色內就有這個功能可以直接新增,沒想到還是要透過光碟內的檔案來安裝

直接利用內鍵功能安裝 dotNet3.5 的錯誤訊息
功能表內就有 dotNet 3.5 可以選擇安裝
選擇替代來源路徑
指定光碟內的 sources\sxs 路徑
這樣就可以完成 dotNet3.5安裝

星期三, 10月 08, 2014

[C#] XML File

MVA Twenty C# Questions Explained - [02 How does one parse XML files?]

MVA 範例
using System.Text;
using System.Xml;

namespace MVATwentyQuestions
{
    class Program
    {
        static void Main(string[] args)
        {
         String xmlString =
      @"
				<bookstore>
                    <book genre="autobiography" isbn="1-861003-11-0" publicationdate="1981-03-22">
                        <title>The Autobiography of Benjamin Franklin</title>
                        <author>
                            <first-name>Benjamin</first-name>
                            <last-name>Franklin</last-name>
                        </author>
                        <price>8.99</price>
                    </book>
                </bookstore>";

         ParseXml(xmlString);
        }
    }

    static void ParseXml(string xmlString)
    {
        // Create a Stringbuilder object to hold the text from the XML file 
        // that we will output later
        StringBuilder output = new StringBuilder();

        // Create an XmlReader
        using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
        {
            reader.ReadToFollowing("book");
            reader.MoveToFirstAttribute();
            string genre = reader.Value;
            output.AppendLine("The genre value: " + genre);

            reader.ReadToFollowing("title");
            output.AppendLine("Content of the title element: " + reader.ReadElementContentAsString());
        }    

        Console.WriteLine(output);
    }

}
[C#] XML File-1

星期二, 10月 07, 2014

[C#] 變更 DataGridView 控件

論壇問題練習
把 DataGridViewTextBoxColumn 控件改為 DataGridViewComboBoxColumn 來呈現
namespace ChangeColControl
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            DataTable dt = new DataTable("Demo");
            dt.Columns.Add("EmpNO", typeof(string));
            dt.Columns.Add("EmpName", typeof(string));
            dt.Columns.Add("WK_ID", typeof(string));
            dt.Columns.Add("WK_Name", typeof(string));
            dt.Rows.Add("201401", "蔡一", "W1", "會計");
            dt.Rows.Add("201402", "鄭二", "W2", "資訊");
            dt.Rows.Add("201403", "張三", "W3", "人事");
            dt.Rows.Add("201404", "李四", "W4", "資材");
            dt.Rows.Add("201405", "王五", "W5", "裝配");
            dt.Constraints.Add("PK", dt.Columns["EmpNO"], true);
            dgvData.DataSource = dt;
            dgvData.AllowUserToAddRows = false;
        }

        private void btnChange_Click(object sender, EventArgs e)
        {
            chgControl();
        }

        private void chgControl()
        {
            // 判斷 ColWK_ID 和 ColWK_Name 欄位是否存在
            if (dgvData.Columns.Contains("ColWK_ID") == false) return;
            if (dgvData.Columns.Contains("ColWK_Name") == false) return;

           // 移除部門相關的 DataGridViewTextBoxColumn 欄位
           dgvData.Columns.Remove("ColWK_ID");
           dgvData.Columns.Remove("ColWK_Name");

           // 建立 DataGridViewComboBoxColumn 資料來源
           DataTable dtWK_Name = new DataTable("dtWK_Name");
           dtWK_Name.Columns.Add("WK_ID", typeof(string));
           dtWK_Name.Columns.Add("WK_Name", typeof(string));
           dtWK_Name.Rows.Add("W1", "會計");
           dtWK_Name.Rows.Add("W2", "資訊");
           dtWK_Name.Rows.Add("W3", "人事");
           dtWK_Name.Rows.Add("W4", "資材");
           dtWK_Name.Rows.Add("W5", "裝配");

           // 建立 DataGridViewComboBoxColumn 欄位
           DataGridViewComboBoxColumn cbo = new DataGridViewComboBoxColumn();
           cbo.HeaderText = "部門";
           cbo.Name = "ColWK_Name";
           cbo.DataPropertyName = "WK_ID";
           cbo.DataSource = dtWK_Name;
           cbo.DisplayMember = "WK_Name";
           cbo.ValueMember = "WK_ID";

           // Insert 可以指定出入順序,Add 則是加在最後面
           dgvData.Columns.Add(cbo);
           dgvData.Refresh();
       }
    }
}

星期五, 10月 03, 2014

[VFP] 報表字型

使用者要指定報表中的字型 - Gulim,但是 VFP 報表內選單卻沒有該字型可以選擇

第一次聽見 Gulim 字型,特定確認是不是 Windows 內定字型,不是的話,又要搞得更複雜了,還好 Gulim 是內定字型

[VFP] 報表字型-1

 VFP 報表介面無法選擇 Gulim 字型

[VFP] 報表字型-2

直接開啟該報表定義檔案,修正 Fontface 欄位內的字型名稱,這樣就可以指定 Gulim 字型啦
[VFP] 報表字型-3

VFP 報表中計可以看見設定後的結果

[VFP] 報表字型-4

星期三, 10月 01, 2014

[C#] String 和 string 區別

MVA Twenty C# Questions Explained - [03 ​What is the difference between String and string?]

整理:
  1. string 是 String 的別名
  2. string 在 C# 中是關鍵字,常用在宣告變數名稱,而 String 在 .NET 中是 Class
  3. string 是內建型別,屬於 C#、String 是通用型別,屬於 .Net Framework,在 VS 中寫 code 時,宣告為 string,但實際在 .NET 內執行時,會轉換為 String 通用型別,不論任何程式語言用到 .NET 的話,都會轉換為通用型別
MVA 範例:說明 string 是 String 的別名,也因此可以用 String.Concat() 來呼叫 Concat 靜態方法
namespace MVATwentyQuestions
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(typeof(string));
            Console.WriteLine(typeof(String));

            string name = "Gerry";
            String name2 = "Gerry 2";

            Console.WriteLine(name);
            Console.WriteLine(name2);

            Console.WriteLine(string.Concat(name, name2));
            Console.WriteLine(String.Concat(name, name2));
        }
    }
}
[C#] String 和 string 區別-1