[英]Calling the base constructor in C#
如果我從基類繼承並想將繼承類的構造函數中的某些內容傳遞給基類的構造函數,我該怎么做?
例如,如果我從 Exception 類繼承,我想做這樣的事情:
class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extraInfo)
{
//This is where it's all falling apart
base(message);
}
}
基本上我想要的是能夠將字符串消息傳遞給基異常類。
將您的構造函數修改為以下內容,以便它正確調用基類構造函數:
public class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extrainfo) : base(message)
{
//other stuff here
}
}
請注意,構造函數不是您可以在方法中隨時調用的東西。 這就是您在構造函數主體中的調用中遇到錯誤的原因。
請注意,您可以在對基本構造函數的調用中使用靜態方法。
class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extraInfo) :
base(ModifyMessage(message, extraInfo))
{
}
private static string ModifyMessage(string message, string extraInfo)
{
Trace.WriteLine("message was " + message);
return message.ToLowerInvariant() + Environment.NewLine + extraInfo;
}
}
如果您需要調用基本構造函數但不是立即調用,因為您的新(派生)類需要進行一些數據操作,最好的解決方案是訴諸工廠方法。 您需要做的是將派生構造函數標記為私有,然后在您的類中創建一個靜態方法,該方法將完成所有必要的工作,然后調用構造函數並返回對象。
public class MyClass : BaseClass
{
private MyClass(string someString) : base(someString)
{
//your code goes in here
}
public static MyClass FactoryMethod(string someString)
{
//whatever you want to do with your string before passing it in
return new MyClass(someString);
}
}
確實使用base
類(某物)來調用基類構造函數,但在重載的情況下使用this
關鍵字
public ClassName() : this(par1,par2)
{
// do not call the constructor it is called in the this.
// the base key- word is used to call a inherited constructor
}
// Hint used overload as often as needed do not write the same code 2 or more times
public class MyExceptionClass : Exception
{
public MyExceptionClass(string message,
Exception innerException): base(message, innerException)
{
//other stuff here
}
}
您可以將內部異常傳遞給構造函數之一。
來自框架設計指南和 FxCop 規則。 :
1.自定義異常應該有一個以異常結尾的名字
class MyException : Exception
2.異常應該是公開的
public class MyException : Exception
如果類型不是密封的,則序列化構造函數受保護,如果類型是密封的,則為私有。 基於MSDN :
[Serializable()] public class MyException : Exception { public MyException() { // Add any type-specific logic, and supply the default message. } public MyException(string message): base(message) { // Add any type-specific logic. } public MyException(string message, Exception innerException): base (message, innerException) { // Add any type-specific logic for inner exceptions. } protected MyException(SerializationInfo info, StreamingContext context) : base(info, context) { // Implement type-specific serialization constructor logic. } }
或者
[Serializable()]
public sealed class MyException : Exception
{
public MyException()
{
// Add any type-specific logic, and supply the default message.
}
public MyException(string message): base(message)
{
// Add any type-specific logic.
}
public MyException(string message, Exception innerException):
base (message, innerException)
{
// Add any type-specific logic for inner exceptions.
}
private MyException(SerializationInfo info,
StreamingContext context) : base(info, context)
{
// Implement type-specific serialization constructor logic.
}
}
您還可以對構造函數中的參數進行條件檢查,這具有一定的靈活性。
public MyClass(object myObject=null): base(myObject ?? new myOtherObject())
{
}
或者
public MyClass(object myObject=null): base(myObject==null ? new myOtherObject(): myObject)
{
}
根據此處列出的其他一些答案,您可以將參數傳遞給基類構造函數。 建議在繼承類的構造函數的開頭調用基類構造函數。
public class MyException : Exception
{
public MyException(string message, string extraInfo) : base(message)
{
}
}
我注意到,在您的示例中,您從未使用過extraInfo
參數,因此我假設您可能希望將extraInfo
字符串參數連接到異常的Message
屬性(似乎在接受的答案和代碼中忽略了這一點你的問題)。
這只需調用基類構造函數,然后使用額外信息更新 Message 屬性即可實現。
public class MyException: Exception
{
public MyException(string message, string extraInfo) : base($"{message} Extra info: {extraInfo}")
{
}
}
public class MyException : Exception
{
public MyException() { }
public MyException(string msg) : base(msg) { }
public MyException(string msg, Exception inner) : base(msg, inner) { }
}
class Exception
{
public Exception(string message)
{
[...]
}
}
class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extraInfo)
: base(message)
{
[...]
}
}
使用較新的 C# 功能,即out var
,您可以擺脫靜態工廠方法。 我剛剛(偶然)發現稱為 inse base-"call" 的方法的 out var 參數流向構造函數主體。
例如,使用您要從中派生的這個基類:
public abstract class BaseClass
{
protected BaseClass(int a, int b, int c)
{
}
}
您要執行的非編譯偽代碼:
public class DerivedClass : BaseClass
{
private readonly object fatData;
public DerivedClass(int m)
{
var fd = new { A = 1 * m, B = 2 * m, C = 3 * m };
base(fd.A, fd.B, fd.C); // base-constructor call
this.fatData = fd;
}
}
解決方案是使用靜態私有輔助方法,該方法生成所有必需的基本參數(如果需要,還可以添加其他數據),並且不使用靜態工廠方法,只需向外部構造簡單的構造函數:
public class DerivedClass : BaseClass
{
private readonly object fatData;
public DerivedClass(int m)
: base(PrepareBaseParameters(m, out var b, out var c, out var fatData), b, c)
{
this.fatData = fatData;
Console.WriteLine(new { b, c, fatData }.ToString());
}
private static int PrepareBaseParameters(int m, out int b, out int c, out object fatData)
{
var fd = new { A = 1 * m, B = 2 * m, C = 3 * m };
(b, c, fatData) = (fd.B, fd.C, fd); // Tuples not required but nice to use
return fd.A;
}
}
public class Car
{
public Car(string model)
{
Console.WriteLine(model);
}
}
public class Mercedes : Car
{
public Mercedes(string model): base(model)
{
}
}
用法:
Mercedes mercedes = new Mercedes("CLA Shooting Brake");
輸出:CLA 射擊剎車
添加: base("string or something")
在構造函數之后,而不是在其主體內。
public class MyException : System.Exception {
public MyException(string msg) : base(msg) {
// code here
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.