2015-08-05 39 views
6

Tôi đã viết mã bên dưới và biên dịch thành công.Tôi có thể tạo hàm tạo cho Enum không?

class Program 
{ 
     enum Fruits 
     { 
      Apple, 
      Mango, 
      Banana 
     } 

     static void Main(string[] args) 
     { 
      Fruits f = new Fruits(); 
     } 
} 

Mặc dù Fruits được một enum, biên dịch và thông dịch viên được cho phép tôi viết những dòng này. Điều này có nghĩa là tôi có thể tạo ra một hàm tạo cho một enum? nếu có thì làm thế nào?

+1

bạn muốn đạt được điều gì với nhà xây dựng như vậy? –

+1

Tôi có thể muốn ghi đè hành vi mặc định của việc trả lại Apple theo mặc định, chỉ cần suy nghĩ to. – yogi

+0

Bạn có thể thay đổi mặc định bằng cách thay đổi thứ tự các thay thế enum được liệt kê. –

Trả lời

4

Không, bạn không thể.

new Fruits() sẽ trả lại giá trị mặc định (giá trị tương ứng với 0 trong loại cơ bản của enum), nó giống như default(Fruits) (hoặc Fruits.Apple trong trường hợp của bạn).

Hãy nhớ rằng các enums chỉ bao bọc quanh kiểu nguyên thủy (theo mặc định là int). Bạn có thể so sánh khá nhiều new Fruits() đến new int().

Thông thường, bạn không sử dụng các cú pháp new Fruits()/new int() vì nó là phổ biến hơn để chỉ cần viết 0 hoặc default(T), nhưng bạn có thể muốn sử dụng nó trong mã chung. Ví dụ:

public T NewInstance<T>() 
    where T : new() 
{ 
    return new T(); 
} 

Bạn được phép gọi NewInstance<Fruits>(), số này sẽ trả lại Fruits.Apple.

+0

Cú pháp Đường tới 'int' –

+1

' int() 'hoạt động trong .NET 1.0, trước khi dùng Generics. Đó là một lợi thế, nhưng không phải là một lý do. –

+0

@Jon Cảm ơn bạn đã nhập, tôi hoàn toàn quên .NET 1.0. Tôi viết lại câu trả lời. –

1

No. Kiểm tra đầu ra IL (được tạo trong LINQPad). Nó không thực sự gọi một nhà xây dựng ở tất cả. Thay vào đó, nó lưu trữ giá trị số nguyên 0 bên trong một biến cục bộ được gọi là f. Đây là chính xác cùng một đầu ra khi bạn nhận được khi bạn sử dụng một loại đúc để enum.

Theo như trình biên dịch liên quan, Fruits f = new Fruits(); giống với Fruit f = (Fruit)0;.

Fruits f = new Fruits() IL

Program.Main: 
IL_0000: nop   
IL_0001: ldc.i4.0  
IL_0002: stloc.0  // f 
IL_0003: ret   

Program..ctor: 
IL_0000: ldarg.0  
IL_0001: call  System.Object..ctor 
IL_0006: ret 

Để so sánh, đây là đầu ra IL của một lớp bình thường. Nhìn vào IL_001 trong Program.Main nơi nó thực sự gọi một hàm tạo cho lớp đó.

Program.Main: 
IL_0000: nop   
IL_0001: newobj  UserQuery+Program+Fruits..ctor 
IL_0006: stloc.0  // f 
IL_0007: ret   

Program..ctor: 
IL_0000: ldarg.0  
IL_0001: call  System.Object..ctor 
IL_0006: ret   

Fruits..ctor: 
IL_0000: ldarg.0  
IL_0001: call  System.Object..ctor 
IL_0006: ret   
3

C# Spec:

Một kiểu enum là một loại giá trị khác biệt với một tập hợp các hằng số có tên.

Đối với các giá trị mặc định (như đã giải thích trong câu trả lời khác):

Giá trị mặc định của bất kỳ loại enum là giá trị không thể thiếu zero chuyển đổi sang kiểu enum. Trong trường hợp các biến được tự động khởi tạo thành giá trị mặc định, đây là giá trị được gán cho các biến số của các loại enum. Để giá trị mặc định của kiểu enum là dễ dàng có sẵn, chữ 0 ẩn hoàn toàn chuyển thành bất kỳ loại enum nào.

Di chuyển hằng số mặc định thành vị trí đầu tiên trong enum của bạn.

1

Đối với bất kỳ loại giá trị nào, có một hàm tạo tham số trả về giá trị bằng 0. Do đó:

var val = new int(); // 0 
var val = new double(); // 0.0 
var val = new DateTime(); // 0001-01-01T00:00:00.000000 Unspecified timezone 
var val = new StringSplitOptions(); // StringSplitOptions.None 

Tuy nhiên:

  1. Bạn không thể thêm một constructor mới cho một loại đó không phải là một struct hoặc một class, và do đó càng xa càng giá trị loại đi, chỉ struct.
  2. Bạn không thể thay đổi việc triển khai bất kỳ nhà thầu mặc định nào trong số này.

Trong trường hợp enum s và nguyên thủy, hàm tạo thậm chí không được khai báo.

Do đó bạn không thể tạo một hàm tạo như vậy.

(Nói đúng, .NET cho phép bạn đặt một hàm tạo tham số không xác định trên struct nhưng C# không và nếu bạn thực hiện trong CIL thô thì có các quy tắc không nhất quán khi được gọi và khi bạn sẽ chỉ nhận được một thể hiện tất cả 0 được tạo).

Các vấn đề liên quan