在JavaScript中判斷變數是否存在
if (typeof(_varName) == 'undefined')
…the variable is not exist.
在jQuery中判斷下拉選單裡是否有特定value的option存在
if (jQuery("#" + _objId + " option[value='" + _value + "']").length > 0)
在JavaScript中判斷變數是否存在
if (typeof(_varName) == 'undefined')
…the variable is not exist.
在jQuery中判斷下拉選單裡是否有特定value的option存在
if (jQuery("#" + _objId + " option[value='" + _value + "']").length > 0)
提供JSON的格式資料,但是不要將所有的entity欄位都輸出.
輸出所有欄位
1: using (MyStockEntities entities = new MyStockEntities())
2: {3: JavaScriptSerializer js = new JavaScriptSerializer();
4: return js.Serialize(entities.CodeStocks);
5: }
輸出需要的欄位
1: using (MyStockEntities entities = new MyStockEntities())
2: {3: JavaScriptSerializer js = new
4: JavaScriptSerializer();5: var results = from cols in entities.CodeStocks
6: select new
7: { 8: StockId = cols.StockId, 9: StockName = cols.StockName, 10: StockType = cols.StockType 11: };12: return js.Serialize(results);
13: }在asp時代,要作cache通常是用application來存資料,
要完整一點的.就是自己寫個class來操作application控制要cache的資料.
但是在asp.net,頁面要cache變得簡單許多.
只要一行
<%@ OutputCache Duration="60" VaryByParam="None" %>
就可以了,
但是,現在問題又來了,
客戶希望後台新增完後他要立即可以從前台看到更新的資料.
先前在網路上看到是有說只要頁面有修改outputcache就會被清除.
但是...這是在測試時候的方式,
在production環境的頁面應該是不能讓客戶每次更新完就去動一下頁面.
要解決這問題,
可以使用HttpResponse.RemoveOutputCacheItem
用法如下 :
HttpResponse.RemoveOutputCacheItem("/default.aspx");
假設你的default.aspx有設定了outputcache,那你可以新增一個管理cache的頁面.
在那個頁面上有個按鈕,點下後呼叫上面的程式.
而RemoveOutputCacheItem所帶的參數就是你的頁面的絕對路徑(不能使用"../"這種相對路徑).
測試網址:
OutputCache頁面 : http://vip.blueshop.com.tw/ajun/cachetest.aspx
Cache管理頁面 : http://vip.blueshop.com.tw/ajun/cachemanager.aspx
outputCache頁面在上一篇介紹過了,而管理的頁面中有兩個功能,
remove cache才是這次的測試範例.
只要確定網址正確,按下remove cache後,該頁面的outputcache就會被清除,
再次瀏覽outputcache的頁面後就會是被更新後的資料了.
問題到這大致上已經ok了,
但是...還是有點狀況,
因為後台維護的資料是最新消息,
而除了首頁外,還有其他的頁面也都會顯示最新消息,
所以如果要用RemoveOutputCacheItem一筆一筆清除cache似乎有點麻煩,
所以下一篇將會是說明怎麼處理這樣的問題.
ps.範例中有這個的程式碼,如果等不及想要知道解決方案的話,可以直接看code.
作網站的首頁的時候,通常為了增加效能,都會作一些cache的動作,
而在asp.net中,要作將網頁作cache很簡單,
如果要cache整個頁面,只要在aspx中加上下面這段
<%@ OutputCache Duration="60" VaryByParam="None" %>
這樣可以讓你的頁面cache 60秒.
如果你的網址如下
ShowCity.aspx?city=101
也就是會因為參數不同而有不同結果,而你也希望能快取這些頁面,
那就將設定改為
<%@ OutputCache Duration="60" VaryByParam="city" %>
如果有多個參數的話,那就以分號(;)區隔就可以了,例如
<%@ OutputCache Duration="60" VaryByParam="city;zipcode" %>
可是現在問題來了.
如果首頁都是公開的資料那也就沒有甚麼問題,
但是現在首頁要放個登入者的名稱,
讓使用者知道自己已經登入,而且知道自己叫甚麼名字.
而整頁作outputcache的話,一連到網頁可能會看到別人的名字...
一開始,是用ajax的方式,在也面呈現以後,
透過javascript去呼叫一隻aspx取得登入資料,然後顯示在某個div裡面.
但後來發現asp.net 2.0中有個Substitution的控制項可以解決這樣的問題,
而Substitution 的用法如下:
aspx
<asp:Substitution ID="Substitution1" runat="server" MethodName="GetDateTime" />
aspx.cs
public static string GetDateTime(HttpContext context)
{
return "主機時間 : " + DateTime.Now.ToString();
}
範例網址 : http://vip.blueshop.com.tw/ajun/cachetest.aspx
點選上面的範例網址,然後重新整理幾次,
你會發現上面的主機時間60秒才會更新.
但下面的主機時間是每次都會更新.
參考網址:
http://dotnetjunkies.com/QuickStartv20/aspnet/doc/ctrlref/standard/substitution.aspx
用ado.net的connection.GetSchema取得資料表結構算是蠻方便的.
但差的一點就是取不到欄位的說明.
因為又要開始寫文件了.而之前寫的SchemaGen不能支援MS SQL 2005.
所以現在正在著手寫SchemaGen 2005版.
另外也練習使用所謂的design pattern來進行...
至於用哪個...先試試看再說...
回到主題.
之前其實有寫過相關的主題.
不過當初主要是說明用T-SQL維護欄位的描述.
現在再針對::fn_listextendedproperty加一些說明
如果要針對某個資料表的某個欄位取得
可以使用下面的語法
select value form ::fn_listextendedproperty(NULL, 'user', 'dbo', 'table', N'資料表名稱', 'column', N'欄位名稱')
如果要取得某個資料表中所有欄位說明的話,可以使用
select * form ::fn_listextendedproperty(NULL, 'user', 'dbo', 'table', N'資料表名稱', 'column',NULL)
另外.如果你的資料表也有設定說明的話,
可以使用下面的語法取得資料表的說明
select * form ::fn_listextendedproperty(NULL, 'user', 'dbo', 'table', N'資料表名稱',NULL,NULL)
當然.要取的所有資料表的說明就是用下面這個
select * form ::fn_listextendedproperty(NULL, 'user', 'dbo', 'table',NULL,NULL,NULL)
另外,上面的參數中有使用NULL的,也可以改用default.意義應該是相同的.例如
select * form ::fn_listextendedproperty(default, 'user', 'dbo', 'table',default,default,default)
而修改或是新增欄位或是資料表說明的話,
可以參考上次寫的T-SQL維護欄位的描述,
使用sp_addextendedproperty及sp_updateextendedproperty來處理
相關連結 :
fn_listextendedproperty (Transact-SQL)
http://msdn2.microsoft.com/en-us/library/ms179853.aspx
sp_addextendedproperty (Transact-SQL)
http://msdn2.microsoft.com/en-us/library/ms180047.aspx
sp_updateextendedproperty (Transact-SQL)
http://technet.microsoft.com/zh-tw/library/ms186885.aspx
之前有個朋友拿個vb6的程式給我.
說這是他請別人寫的,需要密碼才能開啟使用,
可是他忘了密碼是甚麼,而且沒有原始碼,
希望看看有沒有辦法"找到".
程式的功能是甚麼已經有點不記得了,因為不是重點.
重點是他的密碼並沒有在資料庫中,因為翻遍資料庫(Access)中的資料表沒有找到任何訊息.
所以猜測密碼應該是在包在程式裡了.
所以直接用十六進位編輯器(ultraedit)開啟那個執行檔.
在檔案中看到password的字樣,而就在附近看到了"疑似"密碼的字串.
然後使用那個密碼試著登入.果然真的是密碼...
不知道各位看了上面這個例子會有甚麼想法!!
回到主題.
今天要介紹的是ildasm跟ilasm的功能.
在msdn上的介紹寫著 :
MSIL 反組譯工具是 MSIL 組譯工具 (Ilasm.exe) 的附屬工具。Ildasm.exe 使用包含 Microsoft Intermediate Language (MSIL) 程式碼的可攜式執行檔 (PE),並建立可以做為 Ilasm.exe 的輸入檔的文字檔。
如果你跟我一樣看了還是不懂他是用來做甚麼的話,那就先往下看.
為了測試,我們要先寫個主控台程式(ConsoleApplication).
主要的功能如下:
讓使用者輸入帳號密碼,
然後判斷是否跟我們設定好的字串相同.
如果相同就顯示welcome,
如果不同就顯示Access Deny.
程式碼如下:
using System;
namespace LoginConsole
{
class Program
{
static void Main(string[] args)
{
string UserId = "ajun";
string UserPwd = "password";Console.Write("Please enter your id : ");
string uid = Console.ReadLine();
Console.Write("Please enter your password : ");
string pwd = Console.ReadLine();if ((uid == UserId) && (UserPwd == pwd))
{
Console.WriteLine("Welcome!");
}
else
{
Console.WriteLine("Access Deny!");
}
}
}
}
寫好後編譯成exe檔.(假設我們編譯完後的執行檔的名稱為 LoginConsole.exe)
然後開啟一個dos視窗.
因為我是用vs.net 2005.
所以要將路徑切換到到
C:\Windows\Microsoft.NET\Framework\v2.0.50727
因為ildasm.exe是放在這個路徑下.
當然.如果你是透過"Visual Studio 2005命令提示字元"啟動命令視窗的話,就不用切換目錄了.
然後執行下列的指令 :
ildasm LoginConsole.exe
這時就會跳出ildasm的視窗如下 :
點開其中的 Main : void(string[])
就可以看到如下反組譯的視窗畫面
而內容如下 :
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 程式碼大小 104 (0x68)
.maxstack 2
.locals init ([0] string UserId,
[1] string UserPwd,
[2] string uid,
[3] string pwd,
[4] bool CS$4$0000)
IL_0000: nop
IL_0001: ldstr "ajun"
IL_0006: stloc.0
IL_0007: ldstr "password"
IL_000c: stloc.1
IL_000d: ldstr "Please enter your id : "
IL_0012: call void [mscorlib]System.Console::Write(string)
IL_0017: nop
IL_0018: call string [mscorlib]System.Console::ReadLine()
IL_001d: stloc.2
IL_001e: ldstr "Please enter your password : "
IL_0023: call void [mscorlib]System.Console::Write(string)
IL_0028: nop
IL_0029: call string [mscorlib]System.Console::ReadLine()
IL_002e: stloc.3
IL_002f: ldloc.2
IL_0030: ldloc.0
IL_0031: call bool [mscorlib]System.String::op_Equality(string,
string)
IL_0036: brfalse.s IL_0044
IL_0038: ldloc.1
IL_0039: ldloc.3
IL_003a: call bool [mscorlib]System.String::op_Equality(string,
string)
IL_003f: ldc.i4.0
IL_0040: ceq
IL_0042: br.s IL_0045
IL_0044: ldc.i4.1
IL_0045: stloc.s CS$4$0000
IL_0047: ldloc.s CS$4$0000
IL_0049: brtrue.s IL_005a
IL_004b: nop
IL_004c: ldstr "Welcome!"
IL_0051: call void [mscorlib]System.Console::WriteLine(string)
IL_0056: nop
IL_0057: nop
IL_0058: br.s IL_0067
IL_005a: nop
IL_005b: ldstr "Access Deny!"
IL_0060: call void [mscorlib]System.Console::WriteLine(string)
IL_0065: nop
IL_0066: nop
IL_0067: ret
} // end of method Program::Main
而從這內容就可以很清楚的看到我們所設定的帳號密碼.
到這.我想大家應該比較清楚ildasm.exe的功能了.
再來在說一下ilasm.exe,
ildasm是用來做反組譯的,
而ilasm就是用來作組譯用的.
至於怎麼用.看一下下面的用法.
現在我們先用ildasm.exe來產生剛剛所寫的程式的PE檔.
語法如下 :
ildasm /source LoginConsole.exe /out:LoginConsoleFake.txt
其中的/source參數是用來"顯示原始程式行做為註解".
然後我們就可以得到下面這個LoginConsoleFake.txt的檔案.
// Microsoft (R) .NET Framework IL Disassembler. Version 2.0.50727.42
// Copyright (c) Microsoft Corporation. All rights reserved.// Metadata version: v2.0.50727
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 2:0:0:0
}
.assembly LoginConsole
{
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 ) // ...1.0.0.0..
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 65 30 31 65 31 37 32 31 2D 37 32 62 63 // ..$e01e1721-72bc
2D 34 33 61 62 2D 38 65 62 62 2D 34 66 66 38 34 // -43ab-8ebb-4ff84
31 62 65 34 65 37 36 00 00 ) // 1be4e76..
.custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 13 43 6F 70 79 72 69 67 68 74 20 28 43 29 // ...Copyright (C)
20 20 32 30 30 38 00 00 ) // 2008..
.custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 0C 4C 6F 67 69 6E 43 6F 6E 73 6F 6C 65 00 // ...LoginConsole.
00 )
.custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 )
.custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 0C 4C 6F 67 69 6E 43 6F 6E 73 6F 6C 65 00 // ...LoginConsole.
00 )// --- 以下為自動加入的自訂屬性,請勿取消註解 -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ).custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.hash algorithm 0x00008004
.ver 1:0:0:0
}
.module LoginConsole.exe
// MVID: {71069530-5126-4026-B70A-03F69CFFD29A}
.imagebase 0x00400000
.file alignment 0x00001000
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x009C0000// =============== CLASS MEMBERS DECLARATION ===================
.class private auto ansi beforefieldinit LoginConsole.Program
extends [mscorlib]System.Object
{
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 程式碼大小 104 (0x68)
.maxstack 2
.locals init ([0] string UserId,
[1] string UserPwd,
[2] string uid,
[3] string pwd,
[4] bool CS$4$0000)
.language '{3F5162F8-07C6-11D3-9053-00C04FA302A1}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
// Source File 'D:\Project\LoginConsole\LoginConsole\Program.cs'
//000010: {
IL_0000: nop
//000011: string UserId = "ajun";
IL_0001: ldstr "ajun"
IL_0006: stloc.0
//000012: string UserPwd = "password";
IL_0007: ldstr "password"
IL_000c: stloc.1
//000013:
//000014: Console.Write("Please enter your id : ");
IL_000d: ldstr "Please enter your id : "
IL_0012: call void [mscorlib]System.Console::Write(string)
IL_0017: nop
//000015: string uid = Console.ReadLine();
IL_0018: call string [mscorlib]System.Console::ReadLine()
IL_001d: stloc.2
//000016: Console.Write("Please enter your password : ");
IL_001e: ldstr "Please enter your password : "
IL_0023: call void [mscorlib]System.Console::Write(string)
IL_0028: nop
//000017: string pwd = Console.ReadLine();
IL_0029: call string [mscorlib]System.Console::ReadLine()
IL_002e: stloc.3
//000018:
//000019: if ((uid == UserId) && (UserPwd == pwd))
IL_002f: ldloc.2
IL_0030: ldloc.0
IL_0031: call bool [mscorlib]System.String::op_Equality(string,
string)
IL_0036: brfalse.s IL_0044IL_0038: ldloc.1
IL_0039: ldloc.3
IL_003a: call bool [mscorlib]System.String::op_Equality(string,
string)
IL_003f: ldc.i4.0
IL_0040: ceq
IL_0042: br.s IL_0045IL_0044: ldc.i4.1
IL_0045: stloc.s CS$4$0000
IL_0047: ldloc.s CS$4$0000
IL_0049: brtrue.s IL_005a//000020: {
IL_004b: nop
//000021: Console.WriteLine("Welcome!");
IL_004c: ldstr "Welcome!"
IL_0051: call void [mscorlib]System.Console::WriteLine(string)
IL_0056: nop
//000022: }
IL_0057: nop
IL_0058: br.s IL_0067//000023: else
//000024: {
IL_005a: nop
//000025: Console.WriteLine("Access Deny!");
IL_005b: ldstr "Access Deny!"
IL_0060: call void [mscorlib]System.Console::WriteLine(string)
IL_0065: nop
//000026: }
IL_0066: nop
//000027: }
IL_0067: ret
} // end of method Program::Main.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// 程式碼大小 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor} // end of class LoginConsole.Program
// =============================================================
// *********** 反組譯作業完成 ***********************
// 警告: 已建立 Win32 資源檔 LoginConsoleFake.res
再來我們將這個檔案做些小調整.
從檔案中我們可以很容易看出哪個是帳號密碼的設定.
所以我們直接改一下密碼.將他改為1234.
IL_0007: ldstr "password"
改為
IL_0007: ldstr "1234"
存檔後.在dos的視窗輸入下列指令
ilasm LoginConsoleFake.txt
當執行完成後,它會產生一個LoginConsoleFake.exe的檔案.
這時你就可以執行它.然後輸入新的密碼看看!!
我想這時你應該對於ildasm跟ilasm有初步的認識了...
雖然這並不是一個很正面的例子.
但是,我想應該是可以讓人比較有興趣...
其實,ildasm有更正面的用法,
像是黑暗執行緒寫的這篇,
或是你想要看看對於sqlconnection使用using跟使用close()與Dispose(),
在編譯後所進行的動作有甚麼差異.
也都是可以透過這個工具來進行.
最後,你或許會覺得.net的程式就這麼"透明",這麼不安全嗎??
其實有攻就有防.
下個主題或許可以來說一下.net的"混淆器"(obfuscator).
DateTime的欄位內容為 2007/12/27 18:26:29.597
現在想要只取得2007/12/27而且要保持為日期型態.
也就是要取得2007/12/27 00:00:00的結果
原本是想用format的方式來取得字串結果,然後再轉型態.
不過這樣的語法似乎太長了點.
所以改成下面的方式
select dateadd(dd,0,datediff(dd,0,getdate()))
先使用datediff取得該日期的數值,
再使用dateadd去取得此數值所代表的日期.
雖然使用select cast(getdate() as int)雖然也是可以將日期轉為數值,
但是只要超過12:00就會取得隔天的日期(應該是4捨5入的原因)
select cast('2007/12/27 12:00:00' as datetime)
-- 2007-12-27 12:00:00 000
select cast(cast('2007/12/27 12:00:00' as datetime) as int)
-- 39442
select cast('2007/12/27 11:59:59' as datetime)
-- 2007-12-27 11:59:59
select cast(cast('2007/12/27 12:59:59' as datetime) as int)
-- 39941
所以還是使用datediff的方式來取得日期的數值比較好.
今天發現幾個不錯的紙模型網站
第一彈 : EX-S 鋼彈
原創者的網誌:http://blog.naver.com/7200ss
不過現在很難找到下載點了.所以要用力google一下
GUNDAM紙模型的下載與作品
如果是鋼彈迷的話可以到這挖寶,不過可能手腳要快點.
Canon的Creative Park
裡面的3D-papercraft有許多紙模型可以下載,
如果有打算做個城鎮的話,可以看一下他的craftown,
沒太多錢可以弄個鐵道模型城鎮的話,可以先玩玩這個.
另外他的buildings看起來也是超優的!
YAMAHA的Paper Craft
既然是YAMAHA的網站,
主要的當然就是摩托車的紙模型了!
不過除了摩托車外,還有一些動物及日本風情的紙模型也是不錯的!
另外,還有提供紙模型的教學
http://www.yamaha-motor.co.jp/global/entertainment/papercraft/howto/index.html
影片式的教學讓你一看就懂.
http://www.yamaha-motor.co.jp/global/entertainment/papercraft/howto/0002.html
3D紙模型網
我想只要有在玩紙模型的應該都知道這個網站!!
真的要去買台彩色印表機了...
不然我的機器人都只能是鐵灰色的...
今天收到一個問題,
是要將時間格式顯示為
Thu,13 Dec 2007 08:23:41 +08:00
大致上先想到的是取得格林威治時間
也就是用
DateTime.Now.ToUniversalTime().ToString()
因為台灣的時區是 +8,
所以取得的時間會是台灣時間減8小時.
他這樣的格式會顯示
2007/12/13 上午 08:23:41
然後在ToString()的格式加上"r"
如 :
DateTime.Now.ToUniversalTime().ToString("r");
這樣的結果會顯示
Thu, 13 Dec 2007 08:23:41 GMT
已經有點接近我們要的格式了,
不過還少了+08:00
查了一下,可以在格式中加個zzz來達成
但是zzz跟r似乎是不能一起使用.
所以改成如 :
DateTime.Now.ToUniversalTime().ToString("ddd,d MMM yyyy hh:mm:ss zzz");
這樣的結果變成
星期四,13 十二月 2007 08:23:41 +08:00
因為作業系統的地區與語言選項的設定是預設的中文(台灣)
所以會顯示中文字在時間字串中.
所以要再使用CultureInfo改一下.
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("en-US");
DateTime.Now.ToUniversalTime().ToString("ddd,d MMM yyyy hh:mm:ss zzz",ci);
這時資料就會是以英文(美國)的格式呈現,如下:
Thu,13 Dec 2007 08:23:41 +08:00
上面這樣大致上就可以得到我們要的結果,
不過,每次顯示都要再丟ci進去.
所以,如果不想每次都丟ci的話,
那就是再加一行code
如下
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("en-US");
System.Threading.Thread.CurrentThread.CurrentCulture = ci;
DateTime.Now.ToUniversalTime().ToString("ddd,d MMM yyyy hh:mm:ss zzz");
到此.收工.
參考資料 :
Standard DateTime Format Strings
http://msdn2.microsoft.com/en-us/library/az4se3k1(VS.71).aspx
Custom DateTime Format Strings Output Examples
http://msdn2.microsoft.com/en-us/library/hzz3aycd.aspx
CultureInfo 類別
http://msdn2.microsoft.com/zh-tw/library/system.globalization.cultureinfo(VS.80).aspx
改用c# 2.0也一年多了,
最近才發現??的用法.
??這個operator的用法如下
string message = null;
string result = message ?? "message is null";
Console.WriteLine(result); //列印出 message is null
string message = "I am not null";
string result = message ?? "message is null";
Console.WriteLine(result); // 列印出 I am not null
另外,在數值方面,
int x = null;
這樣是會產生編譯錯誤(Cannot convert null to 'int' because it is a non-nullable value type).
所以如果你就是要宣告一個int而可以是個null的內容的話,
那就是用
int? x = null;
再搭配??的用法如下
int? x = null;
int y = x ?? -1;
Console.WriteLine(y.ToString()); //列印出 -1
在MacOS上要使用windows去編譯一些程式常常會遇到一些plamform的問題... - cmake build failed 當使用 cmake -S . -B build 要建立 build system files 原本的專案是在x64上, 所以直接執行會直接使用A...