C#8.0—非空引用類型

来源:https://www.cnblogs.com/ms27946/archive/2019/08/22/Nullable-Refference-In-CSharp8.html
-Advertisement-
Play Games

非空引用類型——C 8.0 原文地址:https://devblogs.microsoft.com/dotnet/try out nullable reference types/?utm_source=vs_developer_news&utm_medium=referral 該新增的特性最關鍵的 ...


非空引用類型——C#8.0

原文地址:https://devblogs.microsoft.com/dotnet/try-out-nullable-reference-types/?utm_source=vs_developer_news&utm_medium=referral

該新增的特性最關鍵的作用是處理泛型和更高級 API 的使用場景。這些都是我們從 .NETCore 上註解衍生過來的經驗。

通用不為 NULL 約束

通常的做法是不允許泛型類型為 NULL。我們給出下麵代碼:

interface IDoStuff<Tin, Tout>
{
    Tout DoStuff(Tin input);
}

這種做法對為空引用和值類型也許令人滿意的。也就是說對 string 或者 or 來說很好,但是對 string?or 卻不是。

這樣可以通過 notnull 約束來實現。

interface IDoStuff<Tin, Tout>
    where Tin: notnull
    where Tout: notnull
{
    Tout DoStuff(Tin input);
}

像下麵這樣的實現類如果沒有應用相同的泛型約束還是會生成一個警告。

//警告:CS8714 - 可空類型參數 TIn 無法匹配 notnull 約束
//警告:CS8714 - 可空類型參數 TOut 無法匹配 notnull 約束
public class DoStuffer<TIn, TOut>: IDoStuff<TIn, TOut>
{
    public TOut DoStuff(TIn input)
    {
        ...
    }
}

修改成下麵版本則無此問題

// No warnings!
public class DoStuffer<TIn, TOut>: IDoStuff<TIn, TOut>
    where TIn : notnull
    where TOut : notnull
{
    public TOut DoStuff(TIn input)
    {
        ...
    }
}

當創建這個類的實例時,如果你用可空引用類型時,也會生成一個警告

//警告:CS8714 - 可空類型參數 string? 無法匹配 notnull 約束
var doStuffer = new DoStuff<string?,string?>();
// no wanings
var doStufferRight = new DoStuff<string,string>();

針對於值類型同樣如此:

// Warning: CS8714 - 類型參數 'int?' 是可為 null 的 無法匹配 'notnull' 約束
var doStuffer = new DoStuff<int?, int?>();

// No warnings!
var doStufferRight = new DoStuff<int, int>();

註意:如果有人編寫如上代碼沒有發生警告,是因為在解決方案下沒有開啟可空驗證,具體在 .csproj 配置如下:

<Project>
  <PropertyGroup>
    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
    <LangVersion>8.0</LangVersion>
    <!-- New name -->
    <Nullable>enable</Nullable>
    
    <!-- Old name while we wait for new name to be everywhere -->
    <NullableContextOptions>enable</NullableContextOptions>
    <Features>strict</Features>
  </PropertyGroup>
</Project>

這個約束條件對於泛型代碼來說是很有用的,當你想要確保使用一個不為 null 的引用類型。一個顯著的例子是 Dictionary<TKey,TValue> 其中的 TKey 現在被約束為 notnull 它不允許使用為 null 的類型作為 key:

// Warning: CS8714 警告內容同上
var d1 = new Dictionary<string?, string>(10);
// 正因如此,不為空的鍵類型使用 null 作為 key 是會有一個警告
var d2 = new Dictionary<string, string>(10);
// Warning: CS8625 - 無法將 null 文本轉換為不為 null 引用類型
var nothing = d2[null];

然而,不是所有的為 null 泛型問題都能通過這種方式解決。這裡我們添加一些屬性標簽,來允許你們在編譯器中影響可 null 分析。

T? 的問題

你可能想知道:當指定一個可 null 引用或值類型的泛型類的時候,為什麼不僅僅只用 T? 不久好了麽?這個答案非常複雜。

T? 的定義上來看,意思就是說它是 “任何可為 null 類型”。但是,這就潛意識在暗示意味著 T 將是 “任何不可為 null 的類型”,這是錯誤的。這在今天用可 null 值類型的 T 是可能的(例如 bool?)。這是因為 T 早就是一個沒有限制的反省類型。使用 T 作為一個無限制的泛型類,這個變化在語義上是不是期望的,並且在已經存在大量的代碼中無疑是災難。

在一個,值得註意的是可 null 引用類型與為 null 的值的類型是不等價的。Nullable 值類型具體映射到會生成一個類,在 .NET 中 int? 實際上 Nullable<int>。但是對於 string?,它實際上還是 string,但是編譯器會生成滑鼠標簽來標記它。這樣做是為了向後相容。換句話說,string? 是一個“冒牌類型”(fake type),int? 卻不是。

為了區分為 null 值類型預計為 null 引用類型,我們用如下模式:

void M<T>(T? t) where T: notnull

這段代碼是說這個參數 T 為 null,並且 T 被約束為 notnull。如果 T 是一個 string,那麼實際上 M 的簽名方法將會成為 M<string>([NullableAttribute] T t)。但是如果 T 是個 int,M 則會變成 M<int>(Nullable<int> t)。這兩個簽名方法本質上就是不通過的,並且這種差異是互相矛盾的。

因為這個問題,null 引用類型以及 null 值類型這兩者具體表現的差異,任何使用 T? 都必須要求你所引用的這個 T 的 classstruct 都要有這個約束。

最後,T? 的存在,都能在 null 值類型和 null 引用類型之間工作,但是不能解決泛型所有的問題。你也許想在單一方向用可 null 類型(比如只在輸入或只在輸出)並且它既不能用 notnull 也不能用 T 和 T? 來表示分開,除非你認為對於輸入輸出分離泛型類。

可 null 先決條件:AllowNullDisallowNull

看下麵這段代碼

public class MyClass
{
    public string MyValue { get; set; }
}

這個 API 在 C#8.0 之前可能也是支持的。但是 string 的意思現在是不為 null 的 string !我們也許希望實際上任然會允許 null 值,但是在 get 總是返回一些 string 的值。這個地方你就可以使用 AllowNull

public class MyClass
{
    private string _innerValue = string.Empty;
    [AllowNull]
    public string MyValue
    {
        get
        {
            return _innerValue;
        }
        set
        {
            _innerValue = value ?? string.Empty;
        }
    }
}

這樣我就能確保我們得到的值總是不為 null 的,並且我類型還是為 string 類型。但是為了向後相容,我們還是想接受 null 值。AllowNull 標簽就能讓你特指這個 setter 接受 null 值。那樣調用就能得到預期結果:

void M1(MyClass mc)
{
    mc.MyValue = null;  //沒有 AllowNull 標簽會有警告
}

void M2(MyClass mc)
{
    Console.WriteLine(mc.MyValue.Length); // ok, 註意這裡沒有警告
}

註意:這裡存在一個 bug ,null 值的分配與 可為 null 的分析衝突了。這在編譯器後續的更新中解決。

考慮下麵代碼:

public static class HandleMethods
{
    public static void DisposeAndClear(ref MyHandle handle)
    {
        ...
    }
}

在這個例子中,MyHandle引用某個資源的句柄。這個 API 的典型用法是我們有一個引用傳遞的不為 null 的實例,但是當它被清除時,這個引用就為 null 了。我們用 DisallowNull 來很好的表示:

public static class HandleMethods
{
    public static void DisposeAndClear([DisallowNull] ref MyHandle? handle)
    {
        ...
    }
}

這個效果就是任何調用者通過傳遞 null 值,那麼就會引發一個警告,但是你企圖用 . 來處理這個被調用的方法也將會發出警告:

void M(MyHandle handle)
{
    MyHandle? local = null; // Create a null value here
    HandleMethods.DisposeAndClear(ref local); // Warning: CS8601 - Possible null reference assignment
    
    // Now pass the non-null handle
    HandleMethods.DisposeAndClear(ref handle); // No warning! ... But the value could be null now
    
    Console.WriteLine(handle.SomeProperty); // Warning: CS8602 - Dereference of a possibly null reference
}

對於那些案例在我們需要的地方,這兩個特性允許我們單方向可為 null 或不為 null。

更正式的講:

AllowNull 標簽允許調用者傳遞 null 值,甚至是如果這個類型不允許為 null。

DisallowNull 標簽不允許調用者傳遞 null 值,甚至是如果這個類型允許為 null。

他們都能任何輸入上指定:

  • 值類型參數
  • in 參數
  • ref 參數
  • 欄位
  • 屬性
  • 索引

重要:這些標簽隻影響那些註解了的方法調用的 null 分析。這些被註解的方法以及介面實現類的主體不遵循這些特性。

Nullable 後置條件:MaybeNullNotNull

請看下麵代碼:

public class MyArray
{
    // 返回結果如果不匹配則預設值
    public static T Find<T>(T[] array, Func<T, bool> match)
    {
        ...
    }

    // 調用的時候不會返回 null
    public static void Resize<T>(ref T[] array, int newSize)
    {
        ...
    }
}

這裡會有另一個問題。我們希望在 Find 方法找到匹配返回 default,它是可 null 的引用類型。我們希望 Resize 方法接受一個可能為 null 的輸入,但是在調用 Resize 之後確保我們想要的 array 值不是 null。同樣,我們用 notnull 約束不能解決。

這個時候輸入 [MaybeNull] 以及 [NotNull] 現在就能想象輸出的可為 null 了。我們只要做需要做些小修改:

public class MyArray
{
    [return: MaybeNull]
    public static T Find<T>(T[] array, Func<T, bool> match)
    {
        ...
    }

    public static void Resize<T>([NotNull] ref T[]? array, int newSize)
    {
        ...
    }
}

然後我們就調用就會有這樣的效果:

void M(string[] testArray)
{
    var value = MyArray.Find<string>(testArray, s => s == "Hello!");
    Console.WriteLine(value.Length); // Warning: 取消引用可能出現的空引用

    MyArray.Resize<string>(ref testArray, 200);
    Console.WriteLine(testArray.Length); // Safe!
}

註意:在 .netcore 3.0 preview 7 下,我的VS2019 16.2.3 版本中以上代碼不會爆出警告,只有在當前域引用可能為 null 的引用才會暴警告:

string value = defalt;
Console.WriteLine(value.Length);//這裡會爆出警告提示

也說明瞭目前的版本還不完善。

第一個方法指定 T 返回的能是 null 值。也就是說當使用調用這個方法返回的結果時,必須要檢查值是否為 null。

第二個方法有一個嚴格的簽名:[NotNull] ref T[]? array。意思是 array 作為輸入能為 null,但是當 Resize 被調用時,array 不能為 null。也就是如果你調用 Resize 之後你在 array 有引用("."),你將不會得到一個警告。因為在 調用Resize 時,array 值永遠不為 null 了。

正式說:

MaybeNull特性允許你返回可為 null 的類型,甚至這個類型不允許為 null。NotNull特性不允許返回的結果的為 null,甚至是本身這個類允許為 null。他們都能指定以下的任何輸出上:

  • 方法返回
  • out 標記參數(在方法調用後)
  • ref 標記參數(在方法調用後)
  • 欄位
  • 屬性
  • 索引

重要提示:這些特性僅僅只是影響對那些被註解的調用方法的調用者可為 null 性的分析。那些被註解的方法主體和類似介面實現的東西一樣不遵循這個這些標簽。我們也許會在下一個特性中加入。

後置條件:MaybeNullWhen(bool)NotNullWhen(bool)

考慮如下代碼片段:

public class MyString
{
    // value 為 null 時為 true
    public static bool IsNullOrEmpty(string? value)
    {
        ...
    }
}

public class MyVersion
{
    // 如果轉換成功,Version 將不會為 null
    public static bool TryParse(string? input, out Version? version)
    {
        ...
    }
}

public class MyQueue<T>
{
    // 如果我們不能將它出隊列,那麼 result 能為 null
    public bool TryDequeue(out T result)
    {
        ...
    }
}

這些方法在 .NET 隨處可見,當返回值是 truefalse 對應於參數的可為 null 性(或者可能位 null)。MyQueue 這個例子有點特殊,因為他是泛型的。TryDequeque 方法如果在它返回 false 時應該給 result 賦值為 null,但是這種情況只有 T 是引用類型下才可以。如果 T 是值類型 struct 結構體,那麼它不會是 null。

所以針對這種情況,我們想做以下三件事:

  1. 如果 IsNullOrEmpty 返回 false,那麼 value 不會為 null
  2. 如果 TryParse 返回 true,那麼 version 不為 null
  3. 如果 TryDequeue 返回 false,那麼 result 能為 null,如果被提供的參數類型是引用類型的話

很遺憾,C# 編譯器並不會將這些方法返回的結果對於參數的可空性關聯起來。

現在有了 NotNullWhen(bool)MaybeNullWhen(bool) 就能對參數進行更細緻的處理:

public class MyString
{
    public static bool IsNullOrEmpty([NotNullWhen(false)] string? value)
    {
        ...    
    }
}

public class MyVersion
{
    public static bool TryParse(string? input, [NotNullWhen(true)]out Version? version)
    {
        ...
    }
}

public class MyQueue<T>
{
    public bool TryDequeue([MaybeNullWhen(false)] out T result)
    {
        ...
    }
}

然後我們就可以這樣調用了:

void StringTest(string? s)
{
    if(MyString.IsNullOrEmpty(s))
    {
        //這裡會有警告
        //Console.WriteLine(s.Length);
        return;
    }
    Console.WriteLine(s.Length);    //安全
}

void VersionTest(string? s)
{
    if (!MyVersion.TryParse(s, out var version))
    {
        // 警告
        // Console.WriteLine(version.Major);
        return;
    }

    Console.WriteLine(version.Major); // Safe!
}
//註意 在我的實驗下,以下代碼並不會像文中註釋中一樣會產生警告
void QueueTest(MyQueue<string> q)
{
    if (!q.TryDequeue(out var s))
    {
        // This would generate a warning:
        // Console.WriteLine(s.Length); //實際上在我VS中是沒有警告的
        return;
    }

    Console.WriteLine(s.Length); // Safe!
}

調用者可以使用與往常一樣的模式處理 api,沒有來自編譯器的任何警告:

  • 如果 IsNullOrEmpty 返回 true,那麼可以安全的在 value 使用 "."
  • 如果 TryParse 返回 trueversion 成功轉換並可以安全使用 “.”
  • 如果 TryDequeue 返回 falseresult 可能為 null,所以要根據實際需要檢查值(例如:當一個類型是值類型結構體時,返回 false 不為 null,但如果為引用類型,那麼它就為 null)

正式的講:

NotNullWhen(bool) 簽名的參數是不為 null 的,甚至這個類型本身不允許為 null,條件依賴於 bool 方法返回的值。MaybeNullWhen(bool) 簽名的參數能為 null,甚至是參數類型本身不允許,條件依賴於方法返回 bool 值。他們能指定任何參數類型。

輸入輸出之間的無 Null 依賴:NotNullIfNotNull(string)

考慮下麵代碼片段:

class MyPath
{
    public static string? GetFileName(string? path)
    {
        ...
    }
}

在這個例子,我們希望能夠返回 null 字元串,並且我們也應該接受一個 null 值作輸入。所以這個方法能完成我想要的效果。

但是,如果 path 不為 null,我們希望確保返回總是能返回一個字元串。即我想要 GetFileName 返回一個不為 null 的值,條件是 path 不為 null。這裡是沒有方法去表達這個意思的。

[NotNullIfNotNull] 就登場了。這個特性能使你的代碼變得更花哨,所以小心的使用它!

這裡我將展示我使用這個 API 的代碼:

class MyPath
{
    [return: NotNullIfNotNull("path")]
    public static string? GetFileName(string? path)
    {
        ...
    }
}

那麼我們調用這個方法就有這樣的效果:

void PathTest(string? path)
{
    var possiblyNullPath = MyPath.GetFileName(path);
    Console.WriteLine(possiblyNullPath);// Warning: 取消引用可能出現空引用
    if(!string.IsNullOrEmpty(path))
    {
        var goodPath = MyPath.GetFileName(path);
        Console.WriteLine(goodPath);// safe 註意:在我的驗證下仍然有警告
    }
}

正式的:

NotNullIfNotNull(string) 特性簽名錶示任何輸出值是不為 null 的,條件依賴於給出的特性指定的名稱參數的可 null 性。它們可以在以下具體結構指定:

  • 方法返回
  • ref 標明的參數

流特性:DoesNotReturnDoesNotReturnIf(bool)

你可以使用多個方法影響程式的控制流。例如,一個異常幫助類方法,調用它將拋出一個異常,或者一個斷言方法,它根據你的輸入是 true 還是 false 來拋出異常。

你也許希望做一些能像 assert 這樣,這個值不為 null,並且我們認為你們會喜歡它,如果編譯器能理解它。

輸入 DoseNotReturnDoseNotReturnIf(bool)。這裡有一些例子來告訴你怎樣使用:

internal static class ThrowHelper
{
    [DoseNotReturn]
    public static void ThrowArgumentNullException(ExceptionArgument arg)
    {
        ...
    }
}

public static class MyAssertionLibrary
{
    public static void MyAssert([DoesNotReturnIf(false)] bool condition)
    {
        ...
    }
}

ThrowArgumentNullException 在方法中被調用時,它會拋出異常。註解在簽名上的 DoesNotReturn 將發出信號給編譯器表示在之後不要進行非 null 分析,因為代碼將會不可達。

MyAssert 被調用時,並且條件傳遞為 false,它會拋出異常。註解的 DoesNotReturnIf(false) 以及裡面的條件參數能夠讓編譯器知道程式流不會繼續往下走,如果條件為 false。當你想要斷言一個值的可空性的時候,這是非常有用的。在代碼 MyAssert(value != null) 路徑之後,那麼編譯器會假使 value 不是 null。

DoesNotReturn 用在方法上。DoesNotReturnIf(bool) 用在輸入參數上。

進化(Evolving)你的註解

一旦你在公開的 API 使用了註解,那你就要考慮一個事實,那就是更新 API 會影響下游:

  • 增加可空性的註解地方,它們可能會給用戶的代碼帶來警告。
  • 移除可空性註解能如此(比如介面實現)

可空註解在你的公有 API 一部分。增加或移除都會帶來警告。我們建議在預覽版本開始這個,並且征求你們的反饋,目標是在一個完整的版本之後不改變任何註解。儘管這不總是可能的,但是我們還是推薦。

Microsoft framwork 和 庫目前的狀態

因為可空型引用類型是新的,主要的 C# Microsoft framwork 和 lib 的作者也還沒有進行合適的註解。

就是說,.NET Core 中的 “Core Lib”,它代表了 .NET Core 共用的 framwork 的 25% 都完整的做了更新。包括了SystemSystem.IO 以及 System.Collections.Generic。我們正在關註對我們的決定的反饋,以便我們做合適的做出調整,在他們的使用變得更加廣泛之前。

儘管任然還有大約 80% 的 CoreFX 需要註解,但是最常用的 APIs 都有了註解。

可空引用類型的線路

目前,我們把整個可空引用類型視為預覽版。它是穩定,但是這個特性涉及到我們自己技術和更好的 .NET 生態。還需要一些時間來完成。

也就是我們鼓勵庫作者使用在他們的庫中開始註解。這個特性只會讓庫變得更好的使用可空能力,幫忙 .NET 更加安全。

在未來的一年左右,我們將繼續提高這個特性以及在 Microsoft frameworks 和 libs 中傳播。

針對語言,特別是編譯器分析,我們將使它增強以至於我們能使你需要做的事最小化,就像使用非空操作符(!)。這些增強都在這裡追蹤。

針對 CoreFX,我們將會維護註解到 80% 的 api,同樣也會根據反饋做出適當的調整。

對於 ASP.NET Core 和 Entity Framework,我們一旦添加到 CoreFX 和 編譯器我們都會添加註解。

我們沒有計划去給 WinForms 和 WPFs 的 APIs 註解,但是我們樂意聽到你們的反饋在不同的事情上。

最後,我們將繼續提高 C# Visual Studio 工具。我們對於這些特性有很多建議去幫助使用這些特性,我們也很喜歡你們的建議。

下一步

如果你仍然在讀以及在你的代碼中沒有嘗試這個特性,特別是你的庫代碼,還請嘗試以及給我們反饋在你感覺有任何異樣。在 .NET 中消除令人意外的 NullReferenceException 還需要漫長的過程,但是我們希望在長時間運行的之後,開發者不用擔心被隱式的空值影響。你們能幫助導我們。試試這個特性,在你的類庫中使用註解。反饋你的經驗

同步至:https://github.com/MarsonShine/Books/blob/master/CSharpGuide/docs/Write_Safe_And_Efficient_Code.md


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 第十二章 Django框架 12.1 伺服器程式和應用程式 伺服器程式負責對socket伺服器進行封裝,併在請求到來時,對請求的各種數據進行整理。應用程式則負責具體的邏輯處理。為了方便應用程式的開發,就出現了眾多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的開發方 ...
  • 一、使用JSONObject來解析JSON數據官方提供的,所以不需要導入第三方jar包;直接上代碼,如下 步驟解讀: 定義一個JSON數組,用於將伺服器返回的數據傳入到一個JSONArray對象中; 然後迴圈遍歷這個JSONArray,從中取出每一個元素(JSONObject對象),接下來只需調用g ...
  • String轉成jsonObject JsonObject json = JsonObject.fromObject(String str) String轉成JsonArray JsonArray jsonArray = JsonArray.fromObject(String str) 在開發過程中 ...
  • Spring Security 解析(二) —— 認證過程   在學習Spring Cloud 時,遇到了授權服務oauth 相關內容時,總是一知半解,因此決定先把Spring Security 、Spring Security Oauth2 等許可權、認證相關的內容、原理及設計學 ...
  • 一、概述 1. 什麼是代理 我們大家都知道微商代理,簡單地說就是代替廠家賣商品,廠家“委托”代理為其銷售商品。關於微商代理,首先我們從他們那裡買東西時通常不知道背後的廠家究竟是誰,也就是說,“委托者”對我們來說是不可見的;其次,微商代理主要以朋友圈的人為目標客戶,這就相當於為廠家做了一次對客戶群體的 ...
  • 本篇概述==> 數組(依舊只敘述與C++不同的地方,或者一些應用方法例子,畢竟語言是共通的,多了也是廢話.jpg) 一,如果創建一維數組,二維數組,以及 N維數組(以此類推)呢 二,數組的一些方法(排序,複製.......) 1. 增強型 For 迴圈 用來取值,不能修改數組裡的值,相當於 普通 f ...
  • 一. 函數式編程 Java8所有的新特性基本基於函數式編程的思想,函數式編程的帶來,給Java註入了新鮮的活力。 下麵來近距離觀察一下函數式編程的幾個特點: 函數可以作為變數、參數、返回值和數據類型。 基於表達式來替代方法的調用 函數無狀態,可以併發和獨立使用 函數無副作用,不會修改外部的變數 函數 ...
  • 可能你是第一次聽說TomatoLog,沒關係,我可以從頭告訴你,通過瞭解番茄日誌,希望能幫助有需要的朋友,番茄日誌處理將大大降低你採集、分析、處理日誌的過程。 ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...