簡體   English   中英

如何在C#中包裝帶有可選參數的方法?

[英]How can I wrap a method with optional parameters in C#?

我有以下C#類(在此簡化):

internal static class Assertions {
    public static void Assert(bool condition, string message = "Assertion failed") {
        if (!condition) { throw new System.Exception(message); }
    }

    public static void NotNull(object o, string message = "Assertion failed") {
        Assert(!Object.ReferenceEquals(o, null), message);
    }

    public static void EtCaetera(..., string message = "Assertion failed") {
        Assert(..., message);
    }
}

如您所見,我有一個Assertions.Assert()方法,帶有可選參數string message = "Assertion failed"

當我圍繞該方法編寫包裝器時,我希望包裝器具有默認的參數string message ,但是我想避免重復默認值( "Assertion failed" ),因為這違反了DRY原理:如果我想要要將消息"Assertion failed"更改為"I crashed" ,我將不得不在許多地方更改該默認值。

如何傳遞可選參數的“缺失”? 我正在尋找類似的東西:

public static void NotNull(object o, string message = Type.Missing) {
    Assert(!Object.ReferenceEquals(o, null), message);
}

另一個選擇是不使用可選參數,並為每個方法提供兩個版本,但這會很快變得麻煩。

可選參數是在編譯時解析的,不會被替換為特殊值,因此此處沒有太多選項。

如果您不想重復自己的話,我的建議是引入一個特殊值(以模仿Type.Missing是什么):

internal static class Assertions {
    public static void Assert(bool condition, string message = null) {
        if (!condition) {
            throw new System.Exception(message ?? "Assertion failed");
        }
    }
}

internal static class Wrapper {
    public static void Assert(bool condition, string message = null) {
        Assertions.Assert(condition, message);
    }
}

這還有另一個(IMO大的)優勢:如果您更改錯誤消息 (或將其本地化 ),則不必更改所有代碼(現有的編譯庫將被更新 )。 不要忘記,在您的原始代碼中,這樣的調用:

Assertions.Assert(value > 0);

將被轉換(和編譯,即使您使用const字段)為:

Assertions.Assert(value > 0, "Assertion failed");

因此,即使您更改默認消息,編譯后的程序集也不會得到更新。

我更喜歡將null作為可選參數的默認值。

internal static class Assertions {
    private const string DefaultMessage = "Assertion failed";

    public static void Assert(bool condition, string message = null) {
        message = message ?? DefaultMessage;
        if (!condition) { throw new System.Exception(message); }
    }

    public static void NotNull(object o, string message = null) {
        message = message ?? DefaultMessage;
        Assert(!Object.ReferenceEquals(o, null), message);
    }

    public static void EtCaetera(..., string message = null) {
        message = message ?? DefaultMessage;
        Assert(..., message);
    }
}

默認值需要在第一個方法(即包裝器)上指定,因為這是將值應用於參數的位置。 Type.Missing是一個特殊的值,在COM互操作中具有含義。 您可以嘗試以下一些適合您需求的選項。

  1. 在基本方法上使用OptionalAttibute ,並在覆蓋的方法上指定默認值。

     class Class2 : Class1 { public override string MethodWithOptParams(string message = "default message") { return base.MethodWithOptParams(message); } } class Class1 { public virtual string MethodWithOptParams([Optional]string message) { return message; } } 
  2. 將默認值聲明為in,並應用與默認值相同的常量。

     class Class2 : Class1 { public override string MethodWithOptParams(string message = DefaultMessage) { return base.MethodWithOptParams(message); } } class Class1 { protected const string DefaultMessage = "default message"; public virtual string MethodWithOptParams(string message = DefaultMessage) { return message; } } 
  3. 在包裝器中將null用作默認值,並對對基本方法的兩個替代調用進行編碼。

     class Class2 : Class1 { public override string MethodWithOptParams(string message = null) { if (message == null) { return base.MethodWithOptParams(); } else { return base.MethodWithOptParams(message); } } } class Class1 { public virtual string MethodWithOptParams(string message = "default message") { return message; } } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM