Câu hỏi Gọi hàm tạo cơ sở trong C #


Nếu tôi kế thừa từ một lớp cơ sở và muốn truyền một cái gì đó từ hàm tạo của lớp được thừa hưởng đến hàm tạo của lớp cơ sở, làm cách nào để làm điều đó?

Ví dụ,

Nếu tôi kế thừa từ lớp Exception, tôi muốn làm một cái gì đó như thế này:

class MyExceptionClass : Exception
{
     public MyExceptionClass(string message, string extraInfo)
     {
         //This is where it's all falling apart
         base(message);
     }
}

Về cơ bản những gì tôi muốn là để có thể vượt qua chuỗi tin nhắn đến lớp cơ sở ngoại lệ.


1156
2017-08-15 07:39


gốc


Nó cũng đáng chú ý bạn có thể chuỗi các nhà xây dựng trong lớp học hiện tại của bạn bằng cách thay thế this cho base. - Quibblesome


Các câu trả lời:


Sửa đổi constructor của bạn thành cái sau để nó gọi hàm tạo của lớp cơ sở đúng:

public class MyExceptionClass : Exception
{
    public MyExceptionClass(string message, string extrainfo) : base(message)
    {
        //other stuff here
    }
}

Lưu ý rằng một hàm tạo không phải là thứ mà bạn có thể gọi bất cứ lúc nào trong một phương thức. Đó là lý do bạn nhận được lỗi trong cuộc gọi của bạn trong phần thân hàm tạo.


1474
2017-08-15 07:40



Tôi nghĩ rằng bạn có thể đã bỏ lỡ điểm. Vấn đề là về việc gọi một nhà xây dựng cơ sở giữa chừng thông qua các nhà xây dựng overriden. Có lẽ kiểu dữ liệu của hàm tạo cơ sở không giống nhau hoặc bạn muốn làm một số dữ liệu đúc trước khi chuyển nó xuống chuỗi. Làm thế nào bạn sẽ hoàn thành một kỳ công như vậy? - Marchy
Nếu bạn cần gọi hàm tạo cơ sở ở giữa ghi đè, sau đó giải nén nó vào một phương thức thực tế trên lớp cơ sở mà bạn có thể gọi một cách rõ ràng. Giả thiết với các nhà xây dựng cơ bản là chúng hoàn toàn cần thiết để tạo một đối tượng một cách an toàn, vì vậy cơ sở sẽ được gọi trước tiên, luôn luôn. - Jon Limjap
Nó Là chỉ là một phương pháp bạn có thể gọi bất cứ lúc nào, IL-khôn ngoan. C # chỉ xảy ra để đặt thêm hạn chế trên đầu trang này. - Roman Starkov
Điều đáng chú ý là base constructor được gọi trước khối phương pháp được truy cập. msdn.microsoft.com/en-us/library/ms173115.aspx - John Weisz
Nó không phải là một thiết kế tốt nếu bạn cần gọi hàm tạo của lớp cơ sở ở giữa trong quá trình khởi tạo của bạn. Ý tưởng của một nhà xây dựng là nó làm tất cả công việc cần thiết để thực hiện nhiệm vụ của mình. Điều này có tác dụng khi khởi tạo của bạn bắt đầu, lớp cơ sở đã được khởi tạo đầy đủ và lớp dẫn xuất là miễn phí để gọi bất kỳ hàm lớp cơ sở nào. Nếu thiết kế của bạn là như vậy mà bạn muốn làm một cái gì đó một nửa cách constructor của bạn, sau đó rõ ràng đây không phải là khởi tạo ans lớp cơ sở như vậy nên không được trong constructor của lớp cơ sở, nhưng trong một chức năng riêng biệt, có thể bảo vệ - Harald Coppoolse


Lưu ý rằng bạn có thể sử dụng tĩnh các phương thức trong lời gọi đến hàm tạo cơ sở.

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;
     }
}

420
2018-04-28 17:34



Lớp Exception bị khóa lại đến mức tôi thấy mình làm việc này một vài lần, nhưng cũng lưu ý nó không phải là thứ bạn nên làm nếu bạn có thể tránh nó. - SMASH
Xin chào @ChrisS, tôi có thể sử dụng như `: base (" thông điệp mặc định của tôi. ")`, Cách sử dụng như thế này? - Carlos
Xin lỗi, C # newb ở đây. Tại sao bạn gọi Trace.WriteLine("message was " + message)? - kdbanman
@kdbanman Điều đó chỉ xuất ra một thông báo gỡ lỗi. Không có mục đích chức năng có liên quan. - Nick Whaley
Câu trả lời chính xác. Câu trả lời được chấp nhận không cho phép tôi xử lý; và followup bình luận trên một workaround  giả sử tôi có quyền truy cập để thay đổi lớp cơ sở; Tôi không. Câu trả lời của nhà máy giả định rằng tôi có thể kiểm soát cách lớp được khởi tạo; Tôi không thể. Chỉ có câu trả lời của bạn cho phép tôi sửa đổi một cái gì đó trước khi chuyển nó vào cơ sở. - The Red Pea


Nếu bạn cần gọi hàm tạo cơ sở nhưng không phải ngay lập tức vì lớp mới (bắt nguồn) của bạn cần thực hiện một số thao tác dữ liệu, giải pháp tốt nhất là sử dụng phương thức nhà máy. Những gì bạn cần làm là đánh dấu private constructor có nguồn gốc của bạn, sau đó thực hiện một phương thức tĩnh trong lớp của bạn sẽ làm tất cả những thứ cần thiết và sau đó gọi hàm khởi tạo và trả về đối tượng.

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);
    }
}

77
2018-02-27 02:22



Đây có thể có khả năng vi phạm các nguyên tắc SOLID (SRP), vì trách nhiệm của việc tạo lớp học là đóng gói với bất kỳ trách nhiệm nào khác mà lớp học được cho là để chăm sóc. Một nhà máy trừu tượng có thể được sử dụng nhưng có thể thêm sự phức tạp không cần thiết vào mã đơn giản. Tất nhiên vi phạm các SOLID là ok nếu bạn biết thương mại và số điện thoại mà nó sẽ đưa vào kiến ​​trúc của bạn (và cách khắc phục bất kỳ vấn đề nào trong tương lai có thể phát sinh từ quyết định thiết kế của bạn). - Sebastien


public class MyExceptionClass : Exception
{
    public MyExceptionClass(string message,
      Exception innerException): base(message, innerException)
    {
        //other stuff here
    }
}

Bạn có thể vượt qua ngoại lệ bên trong cho một trong các hàm tạo.


21
2017-12-04 05:03





Nó là sự thật sử dụng base (cái gì đó) để gọi hàm tạo lớp cơ sở, nhưng trong trường hợp quá tải sử dụng this từ khóa

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

16
2017-11-11 11:32



Tôi thấy những gì bạn đang cố gắng giải thích, và bạn đã đúng. Nếu bạn có hai hàm tạo trong một lớp, bạn có thể tham chiếu một từ khác bằng cách sử dụng từ khóa "này" tương tự như cách bạn sử dụng "cơ sở" khi gọi hàm tạo kế thừa. Tuy nhiên, đây không phải là những gì OP yêu cầu vì vậy đây không thực sự là nơi để thêm điều này. - IAmTimCorey


Từ Hướng dẫn thiết kế khung và quy tắc FxCop.:

1. Ngoại lệ tùy chỉnh phải có tên kết thúc bằng ngoại lệ

    class MyException : Exception

2. Ngoại lệ phải được công khai

    public class MyException : Exception

3. CA1032: Ngoại lệ nên thực hiện các hàm tạo tiêu chuẩn.

  • Một nhà xây dựng không có tham số công khai.
  • Một hàm tạo công khai với một đối số chuỗi.
  • Một hàm tạo công khai với một chuỗi và Ngoại lệ (vì nó có thể bọc một Ngoại lệ khác).
  • Một nhà xây dựng tuần tự hóa được bảo vệ nếu loại không được niêm phong và riêng tư nếu loại được niêm phong. Dựa trên 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.
      }
    }  
    

hoặc là

    [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.
      }
    }  

12
2018-01-24 07:34





Bạn cũng có thể thực hiện kiểm tra có điều kiện với các tham số trong hàm tạo, cho phép một số tính linh hoạt.

public MyClass(object myObject=null): base(myObject ?? new myOtherObject())
{
}

hoặc là

public MyClass(object myObject=null): base(myObject==null ? new myOtherObject(): myObject)
{
}

8
2018-05-27 21:27



Bạn không cần phải loại bỏ các từ "lớp học" từ ví dụ của bạn vì đây là những người xây dựng ... - MarzSocks


class Exception
{
     public Exception(string message)
     {
         [...]
     }
}

class MyExceptionClass : Exception
{
     public MyExceptionClass(string message, string extraInfo)
     : base(message)
     {
         [...]
     }
}

4
2018-02-26 04:11





public class MyException : Exception
{
    public MyException() { }
    public MyException(string msg) : base(msg) { }
    public MyException(string msg, Exception inner) : base(msg, inner) { }
}

4
2018-04-07 12:06



đây là câu trả lời tốt nhất vì nó chứa quá tải của hàm tạo. - vibs2006


Theo một số câu trả lời khác được liệt kê ở đây, bạn có thể chuyển tham số vào hàm tạo lớp cơ sở. Chúng tôi khuyên bạn nên gọi hàm tạo lớp cơ sở của mình ở đầu hàm tạo cho lớp được kế thừa của bạn.

public class MyException : Exception
{
    public MyException(string message, string extraInfo) : base(message)
    {
        this.Message = $"{message} Extra info: {extraInfo}";
        // You can omit the 'this.' portion above...
    }
}

Tôi lưu ý rằng trong ví dụ của bạn, bạn không bao giờ sử dụng extraInfo tham số, vì vậy tôi cho rằng bạn có thể muốn ghép nối extraInfo tham số chuỗi cho Message tài sản của ngoại lệ của bạn (có vẻ như điều này đang bị bỏ qua trong câu trả lời được chấp nhận và mã trong câu hỏi của bạn).

Điều này chỉ đơn giản là đạt được bằng cách gọi hàm tạo lớp cơ sở, và sau đó cập nhật thuộc tính Message với thông tin bổ sung.

Ngoài ra, như Message tài sản được thừa hưởng từ lớp cơ sở, bạn thậm chí không phải gọi hàm tạo lớp cơ sở một cách rõ ràng. Bạn chỉ có thể cập nhật Message thuộc tính trực tiếp từ hàm tạo của lớp được thừa kế của bạn, như sau:

public class MyException : Exception
{
    public MyException(string message, string extraInfo)
    {
        this.Message = $"{message} Extra info: {extraInfo}";
        // You can omit the 'this.' portion above...
    }
}

4
2018-03-14 12:38