日韩欧美国产精品免费一二-日韩欧美国产精品亚洲二区-日韩欧美国产精品专区-日韩欧美国产另-日韩欧美国产免费看-日韩欧美国产免费看清风阁

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

C#.net core 基礎 - “hello”.IndexOf(“\0”,2)中的坑

freeflydom
2024年12月6日 10:49 本文熱度 1293

先想想看,你認為下面代碼返回值是多少?

"hello".IndexOf("", 2);
"hello".IndexOf("\0", 2);
"hello".IndexOf('\0', 2);

今天和大家分享關于.net core中與字符相關的一些奇怪問題。

首先我們先以.NET8目標框架做為測試環(huán)境。直接上代碼: 


using System.Reflection;
using System.Runtime.Versioning;
namespace TestNetCore
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var assembly = Assembly.GetExecutingAssembly();
            var targetFramework = (TargetFrameworkAttribute?)Attribute.GetCustomAttribute(assembly, typeof(TargetFrameworkAttribute));
            if (targetFramework != null)
            {
                Console.WriteLine($"目標框架: {targetFramework.FrameworkName}");
            }
            Console.WriteLine(@"""hello"".IndexOf("""", 2) 結果:" + "hello".IndexOf("", 2));
            Console.WriteLine(@"""hello"".IndexOf(""\0"", 2) 結果:" + "hello".IndexOf("\0", 2));
            Console.WriteLine(@"""hello"".IndexOf('\0', 2) 結果:" + "hello".IndexOf('\0', 2));
            Console.ReadKey();
        }
    }
}

運行結果如下:

 

這與你設想的結果有差別嗎?雖然只是一個方法,三行代碼,但是這里面包含了很多知識點,下面我們就來具體聊聊為什么是這樣的結果,底層邏輯是什么。

相信大多數(shù)人會有一下幾個疑問:

①  為什么查找空字符串返回2

②  為什么查找“\0”也返回2

③  為什么查找‘\0‘又返回-1

1、為什么"hello".IndexOf("", 2)返回2

下面我們一個一個來說,首先來說為什么"hello".IndexOf("", 2)返回2,這個問題比較簡單,就是方法本身定義問題,可以查看官方文檔有詳細說明,如下圖:

 

方法定義如此,如果查詢的值為空字符串,則返回值為startIndex,即查找起始位置索引,因為"hello".IndexOf("", 2)的2表示從索引2處開始查找,所以此這行代碼返回2。

2、為什么"hello".IndexOf("\0", 2)也返回2

雖然這里只是簡單的把空字符串改成了“\0”,但是里的問題就比較復雜了,涉及到多個知識點,首先這里涉及到Unicode編碼問題,當前文化設置問題,以及.NET全球化問題。

我們先回到這個問題,先來看看官方文檔說明,如下圖:

從這里面可以大膽猜測“\0”就是屬于可忽略字符,并且如果查詢的字符串包含了可忽略字符,則結果和移除該字符搜索等效,那么"hello".IndexOf("\0", 2)就等效與"hello".IndexOf("", 2),因此返回2也就順利成章了。

首先我們猜測是正確的,“\0的確屬于可忽略字符,這就是Unicode編碼規(guī)范問題,而且不單單“\0“會有這樣的問題,Unicdoe可忽略字符都會有這樣的問題,比如”\u0010“、”\u001B“等。

Console.WriteLine(@"""hello"".IndexOf(""\u0010"", 2) 結果:" + "hello".IndexOf("\u0010", 2));
Console.WriteLine(@"""hello"".IndexOf(""\u001B"", 2) 結果:" + "hello".IndexOf("\u001B", 2));

執(zhí)行效果如下

 

3、為什么"hello".IndexOf(‘\0’, 2)返回-1

這個答案在上面的官方文檔說明中也可以看到蛛絲馬跡,“在執(zhí)行語言性的或區(qū)分區(qū)域性的比較時該字符不被考慮“,這句話是關鍵,說明IndexOf方法是會受當前文化設置影響的,雖然我們寫的代碼里沒有看到相關當前文化設置,但是不代表沒有,我們可以看下IndexOf相關的重載方法。

 

紅框中StringComparison參數(shù)就可以設置當前文化。我們看看有哪些設置選項。

 

因為"hello".IndexOf("\0", 2)內(nèi)部使用了StringComparison.CurrentCulture  而"hello".IndexOf(‘\0’, 2) 內(nèi)部使用了StringComparison.Ordinal,就是因為CurrentCulture枚舉值導致“在執(zhí)行語言性的或區(qū)分區(qū)域性的比較時”\0“不被考慮“,被直接忽略了,而Ordinal枚舉值不會有這樣的問題,所以沒有被忽略,所以"hello".IndexOf(‘\0’, 2)返回-1。

我們也可以直接調用IndexOf重載方法,指定StringComparison來達到我們想要的效果。

Console.WriteLine(@"""hello"".IndexOf(""\0"", 2, 3, StringComparison.CurrentCulture) 結果:" + "hello".IndexOf("\0", 2, 3, StringComparison.CurrentCulture));
Console.WriteLine(@"""hello"".IndexOf(""\0"", 2, 3, StringComparison.Ordinal) 結果:" + "hello".IndexOf("\0", 2, 3, StringComparison.Ordinal));

運行代碼如下:

 

雖然原因找到了,但是我們再深入思考一下,為什么會有這樣的差異呢?只有IndexOf方法有這樣的問題嗎?

要回答這個問題,就是我們上面提到的.NET全球化問題了。在 .NET 5 前,.NET 全球化 API 在不同的平臺上使用不同的基礎庫。 在 Unix 上,API 使用 Unicode 國際組件 (ICU),在 Windows 上,API 使用 區(qū)域語言支持 (NLS)。 這導致在不同平臺上運行應用程序時,在少數(shù)全球化 API 中存在一些行為差異。 但是以下方面存在明顯的行為差異:區(qū)域性和區(qū)域性數(shù)據(jù)、字符串大小寫、字符串排序和搜索、排序關鍵字、字符串規(guī)范化、國際化域名 (IDN) 支持、Linux 上的時區(qū)顯示名稱。

因此不單單IndexOf方法有這樣的問題,下面這些API都有存在同樣的問題:

?
System.String.Compare
System.String.EndsWith
System.String.IndexOf
System.String.StartsWith
System.String.ToLower
System.String.ToLowerInvariant
System.String.ToUpper
System.String.ToUpperInvariant
System.Globalization.TextInfo(大多數(shù)成員)
System.Globalization.CompareInfo(大多數(shù)成員)
System.Array.Sort(對字符串數(shù)組進行排序時)
System.Collections.Generic.List<T>.Sort()(當列表元素為字符串時)
System.Collections.Generic.SortedDictionary<TKey,TValue>(當鍵為字符串時)
System.Collections.Generic.SortedList<TKey,TValue>(當鍵為字符串時)
System.Collections.Generic.SortedSet<T>(當集包含字符串時)

這里面很多方法都是有多個重載方法的,而每個重載方法默認當前文化設置可能并不相同。因此大家在開發(fā)的時候一定要注意使用,一不小心肯能就好引起一些奇怪的問題,因此大家盡量自己手動指定當前文化設置。

下表列出一些方法其對應的默認行為。

 

:當然如果調用方提供顯式 CultureInfo 或 StringComparison 參數(shù),則該參數(shù)將優(yōu)先于任何默認值。

最后總結一下

1、 IndexOf對于Empty字符查找會返回開始查找索引startIndex,而不是我們想象中的-1;

2、 Unicode可忽略字符受StringComparison參數(shù)影響很大,會直接把相應字符直接忽略掉

3、 .NET全球化進程中,區(qū)域語言支持 (NLS)在向 Unicode 國際組件 (ICU)遷移是必然,因此我們在使用相關方法時一定要小心

4、 如果可以盡量主動顯示設置當前文化區(qū)域設置

轉自https://www.cnblogs.com/hugogoos/p/18387624


該文章在 2024/12/6 10:49:18 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業(yè)務管理,結合碼頭的業(yè)務特點,圍繞調度、堆場作業(yè)而開發(fā)的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 国产精品播放一区二区三区 | 中文字幕在线不卡精品视频99 | 国产精彩香蕉在线视频 | 国产精品日韩在线观看一区二区 | 中文岛国精品亚洲一区 | 亚欧人成| 精品国产爽香蕉在线观看 | 亚洲精品亚洲精品亚洲精品日韩 | 精品成人a区在线观看 | 国产人妖自拍 | 热播电视剧在线观 | 免费?∨中文高清乱 | 国产操操 | 国产人妖ts重口系列网站观看 | 日韩欧美精品综合一区二区三 | 亚洲成熟女人毛毛耸耸多 | 肉色超薄丝袜脚交一区二区 | 337人体做爰大胆视频 | 欧美精品成人a在线观看 | 欧美性受xxxx黑人xyx性爽 | 国产白领邻居在线视频 | 99一区二区三区国产热视频在线 | 高圆圆又紧又大又湿又爽 | 亚洲a级情欲片在线观看 | 男动漫gay片cartoon | 成aⅴ人片在线观看蜜桃 | 国产国产成 | 日本免费三片在 | 国产盗摄电影区9876色 | 强奷乱码中文字幕熟无 | 国产免费私拍一区二区三区 | 国产高清一区二区三区四区 | 国产日韩欧美高清一区二区三区 | 永久免费91桃色福利 | 日本精品 | 国产盗拍精品视频 | 欧美日韩一二三区免费性片 | 国产拍精品亚洲国产高清 | 成人午夜视频精品一区 | 在线观看欧美影 | 国产91青青成人a在线 |