Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the C# compiler allow empty enums?

I accidentally defined an enum today that contained no values. Like this one for example:

public enum MyConfusingEnum{} 

The compiler was quite happy to let me define that and the code built successfully.

Now I obviously can't use that in the traditional sense since the code,..

var mySadCompiler = MyConfusingEnum; 

doesn't specify a value but interestingly enough I was able to say,..

var myRoundTheHousesZeroState = Activator.CreateInstance<MyConfusingEnum>(); 

which, as I've alluded to, is a value type of MyConfusingEnum with the value 0;

My question is why does the compiler allow an empty definition and are there any scenarios where it could be useful?

like image 603
EightyOne Unite Avatar asked May 21 '14 22:05

EightyOne Unite


People also ask

Why does the c exist?

Like the letter G, C emerged from the Phoenician letter gimel (centuries later, gimel became the third letter of the Hebrew alphabet). In ancient Rome, as the Latin alphabet was being adapted from the Greek and Etruscan alphabets, G and C became disambiguated by adding a bar to the bottom end of the C.

Is the letter c useless?

But yeah, here are all the letters from most useless to most useful: X, C, Q, Y, W, H, Z, V, B, D, G, P, E, M, L, U, J, R, F, N, K, A, I, T, S, O. I hope you enjoyed this.

Why does the letter c make two sounds?

In the Latin-based orthographies of many European languages, including English, a distinction between hard and soft ⟨c⟩ occurs in which ⟨c⟩ represents two distinct phonemes. The sound of a hard ⟨c⟩ often precedes the non-front vowels ⟨a⟩, ⟨o⟩ and ⟨u⟩, and is that of the voiceless velar stop, /k/ (as in car).

Does the letter c need to exist?

This is a very important rule considering about 25% of words in our language contain a C.] So why do we need a C? When we combine the C with an H we DO make a unique sound. Without a C we would go to Hurch instead of Church, we would listen to a Hime instead of a Chime, etc.


2 Answers

First off, you could have done that much more easily:

MyConfusingEnum x1 = 0; MyConfusingEnum x2 = default(MyConfusingEnum); MyConfusingEnum x3 = new MyConfusingEnum(); MyConfusingEnum x4 = (MyConfusingEnum) 123; 

all of the above work just fine. (You may be surprised that the first works; see the specification section on implicit enumeration conversions for details.)

My question is why does the compiler allow an empty definition

I'll begin by answering your question with a question. Would you also have the compiler reject?

class C {} interface I {} struct S {} 

Why or why not?

To more directly not answer your question: "why is the world not different than it is?" questions are hard to answer. Instead of answering that impossible question, I'll answer the question "suppose making empty enums an error had been pitched to the design team; how would you have responded to that pitch?" That question is still counterfactual but at least it is one I can answer.

The question then becomes whether the cost of the feature is justified by its benefits.

In order to work a language feature must be thought of, designed, specified, implemeted, tested, documented and shipped to customers. This is a "produce an error" feature, so the error message must be written and translated into some dozen languages, as must the documentation. The five minutes it would have taken me to implement the feature translate into many hours of work by many people who are paid rather a lot.

However, that is not actually the relevant cost. The opportunity cost is the relevant cost. Budgets are finite, features are not free, and therefore any feature which is implemented means some other feature must be cut; which feature of C# would you like to have been cut to get this feature in? The lost benefit from not being able to do a better feature is the opportunity cost.

I note also that your proposed feature has zero obvious benefit to anyone, which would make it a tough sell to the design committee. Perhaps there is a compelling benefit that I'm not seeing; if so, what is it?

are there any scenarios where it could be useful?

None come to mind. "Rejecting programs which are not obviously useful" is not a design goal of C#.

like image 109
Eric Lippert Avatar answered Oct 19 '22 00:10

Eric Lippert


You can cast any value of underlying integer type (I think int by default) to the enum - so (MyConfusingEnum)42 now will be of that enum type.

I don't think it is good idea in general, but there could be cases when "enum" values are coming from external source and code just looks nicer with enum.

Sample (assuming code incapsulates some "int-based state" in Enum:

enum ExternalDeviceState {};  ExternalDeviceState GetState(){ ... return (ExternalDeviceState )intState;} bool IsDeviceStillOk(ExternalDeviceState currentState) { .... } 

Specification does indeed allow empty enum:

14.1 Enum declarations

An enum declaration declares a new enum type. An enum declaration begins with the keyword enum, and defines the name, accessibility, underlying type, and members of the enum.

enum-declaration:    attributesopt   enum-modifiersopt   enum   identifier         enum-base(opt)   enum-body   ;(opt)  enum-base: :   integral-type  enum-body:   {   enum-member-declarations(opt)   }     {   enum-member-declarations   ,   } 

Note that enum-member-declarations(opt) is explicitly marked as variant where nothing is inside {}.

like image 29
Alexei Levenkov Avatar answered Oct 18 '22 23:10

Alexei Levenkov