List of const int instead of enum - c#

I started working on a large c# code base and found the use of a static class with several const ints fields. This class is acting exactly like an enum would.
I would like to convert the class to an actual enum, but the powers that be said no. The main reason I would like to convert it is so that I could have the enum as the data type instead of int. This would help a lot with readability.
Is there any reason to not use enums and to use const ints instead?
This is currently how the code is:
public int FieldA { get; set; }
public int FieldB { get; set; }
public static class Ids
{
public const int ItemA = 1;
public const int ItemB = 2;
public const int ItemC = 3;
public const int ItemD = 4;
public const int ItemE = 5;
public const int ItemF = 6;
}
However, I think it should be the following instead:
public Ids FieldA { get; set; }
public Ids FieldB { get; set; }

I think many of the answers here ignore the implications of the semantics of enums.
You should consider using an enum when the entire set of all valid values (Ids) is known in advance, and is small enough to be declared in program code.
You should consider using an int when the set of known values is a subset of all the possible values - and the code only needs to be aware of this subset.
With regards to refactoring - when time and business contraints allow, it's a good idea to clean code up when the new design/implementation has clear benefit over the previous implementation and where the risk is well understood. In situations where the benefit is low or the risk is high (or both) it may be better to take the position of "do no harm" rather than "continuously improve". Only you are in a position to judge which case applies to your situation.
By the way, a case where neither enums or constant ints are necessarily a good idea is when the IDs represent the identifiers of records in an external store (like a database). It's often risky to hardcode such IDs in the program logic, as these values may actually be different in different environments (eg. Test, Dev, Production, etc). In such cases, loading the values at runtime may be a more appropriate solution.

Your suggested solution looks elegant, but won't work as it stands, as you can't use instances of a static type. It's a bit trickier than that to emulate an enum.
There are a few possible reasons for choosing enum or const-int for the implementation, though I can't think of many strong ones for the actual example you've posted - on the face of it, it seems an ideal candidate for an enum.
A few ideas that spring to mind are:
Enums
They provide type-safety. You can't pass any old number where an enum value is required.
Values can be autogenerated
You can use reflection to easily convert between the 'values' and 'names'
You can easily enumerate the values in an enum in a loop, and then if you add new enum members the loop will automatically take them into account.
You can insert new enunm values without worrying about clashes occurring if you accidentally repeat a value.
const-ints
If you don't understand how to use enums (e.g. not knowing how to change the underlying data type of an enum, or how to set explicit values for enum values, or how to assign the same value to mulitple constants) you might mistakenly believe you're achieving something you can't use an enum for, by using a const.
If you're used to other languages you may just naturally approach the problem with consts, not realising that a better solution exists.
You can derive from classes to extend them, but annoyingly you can't derive a new enum from an existing one (which would be a really useful feature). Potentially you could therefore use a class (but not the one i your example!) to achieve an "extendable enum".
You can pass ints around easily. Using an enum may require you to be constantly casting (e.g.) data you receive from a database to and from the enumerated type. What you lose in type-safety you gain in convenience. At least until you pass the wrong number somewhere... :-)
If you use readonly rather than const, the values are stored in actual memory locations that are read when needed. This allows you to publish constants to another assembly that are read and used at runtime, rather than built into the other assembly, which means that you don't have to recompile the dependant assembly when you change any of the constants in your own assembly. This is an important consideration if you want to be able to patch a large application by just releasing updates for one or two assemblies.
I guess it is a way of making it clearer that the enum values must stay unchanged. With an enum another programmer will just drop in a new value without thinking, but a list of consts makes you stop and think "why is it like this? How do I add a new value safely?". But I'd achieve this by putting explicit values on the enums and adding a clear comment, rather than resorting to consts.
Why should you leave the implementation alone?
The code may well have been written by an idiot who has no good reason for what he did. But changing his code and showing him he's an idiot isn't a smart or helpful move.
There may be a good reason it's like that, and you will break something if you change it (e.g. it may need to be a class due to being accessed through reflection, being exposed through external interfaces, or to stop people easily serializing the values because they'll be broken by the obfuscation system you're using). No end of unnecessary bugs are introduced into systems by people who don't fully understand how something works, especially if they don't know how to test their changes to ensure they haven't broken anything.
The class may be autogenerated by an external tool, so it is the tool you need to fix, not the source code.
There may be a plan to do something more with that class in future (?!)
Even if it's safe to change, you will have to re-test everything that is affected by the change. If the code works as it stands, is the gain worth the pain? When working on legacy systems we will often see existing code of poor quality or just done a way we don't personally like, and we have to accept that it is not cost effective to "fix" it, no matter how much it niggles. Of course, you may also find yourself biting back an "I told you so!" when the const-based implementation fails due to lacking type-safety. But aside from type-safety, the implementation is ultimately no less efficient or effective than an enum.

If it ain't broke, don't fix it.
I don't know the design of the system you're working on, but I suspect that the fields are integers that just happen to have a number of predefined values. That's to say they could, in some future state, contain more than those predefined values. While an enum allows for that scenario (via casting), it implies that only the values the enumeration contains are valid.
Overall, the change is a semantic one but it is unnecessary. Unnecessary changes like this are often a source of bugs, additional test overhead and other headaches with only mild benefits. I say add a comment expressing that this could be an enum and leave it as it is.

Yes, it does help with readability, and no I cannot think of any reason against it.
Using const int is a very common "old school" of programming practice for C++.

The reason I see is that if you want to be loosely coupled with another system that uses the same constants, you avoid being tightly coupled and share the same enum type.
Like in RPC calls or something...

Related

Is there any harm in having many enum values? (many >= 1000)

I have a large list of error messages that my biz code can return based on what's entered. The list may end up with more than a thousand.
I'd like to just enum these all out, using the [Description("")] attribute to record the friendly message.
Something like:
public enum ErrorMessage
{
[Description("A first name is required for users.")]
User_FirstName_Required = 1,
[Description("The first name is too long. It cannot exceed 32 characters.")]
User_FirstName_Length = 2,
...
}
I know enums are primitive types, integers specifically. There shouldn't be any problem with that many integers, right?
Is there something I'm not thinking of? It seems like this should be okay, but I figured I should ask the community before spending the time to do it this way.
Does .Net care about enum types differently when they have lots of values?
Update
The reason I didn't want to use Resources is because
a) I need to be able to reference each unique error message with an integer value. The biz layer services an API, in addition to other things, and a list of integer values has to be returned denoting the errors. I don't believe Resources allows you to address a resource value with an integer. Am I wrong?
b) There are no localization requirements.
I think a design that has 1,000+ values in an enum needs some more thought. Sounds like a "God Enum" anti-pattern will have to be invented for this case.
The main downside I'd point out with having the friendly description in an Attribute is that this will cause challenges if you ever need to localize your app for another language. If this is a consideration, it would be a good idea to put the strings in a resource file.
The enum itself should not be a problem, though having all of your error codes in one master list can be confusing. You may consider creating seperate enums for seperate categories of return codes, as this will make it easier for developers to understand the possible return values for a particular function. You can still give them distinct numeric values (by specifying the numeric values explicitly) if it's important that the codes be unique.
On a side note, the .NET BCL does not make much use of return codes and return codes are somewhat discouraged in modern .NET development. They create maintainability issues (you can almost never remove old return codes or risk breaking backwards compatibility) and they require special validation logic to handle the returns for every call. Stateful validation can be accomplished with IDataErrorInfo, where you use an intermediate class that can represent invalid states, but that only allows a Commit of changes that are validated. This allows you to manipulate the object freely, but also provide feedback to the user as to the validity of its state. The equivalent logic with error codes often requires a switch statement for each use.
1000 is not many, you should just make sure that the underlying integer type is big enough (don't use a char for your enum.
On second thought 1000 is tons if you're manually entering them, if they are generated from some data set it could make sense kinda...
I fully agree with duffymo. An enum with 1000+ values smells bad from y design point of view. Not to mention that it would be quite nasty for the developer to use intelligence on such a GOD ENUM:-)
I would better go for using resources.
I think it's very bad, for error handling you can simply use resource, as i see you want to do reflection and fetch the description its bad too.
If you don't want to use resources, you can define different enum for each of your business rules, Also your different business doesn't need others error message (and shouldn't be like this).

Structs - real life examples? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
There are any number of questions here on SO dealing with the differences between Structs and Classes in C#, and when to use one or the other. (The one sentence answer: use structs if you need value semantics.) There are plenty of guidelines out there about how to choose one or the other, most of which boil down to: use a class unless you meet these specific requirements, then use a struct.
This all makes sense to me.
However, I can't seem to find any real-life examples of people using structs in a system. I'm (semi-)new to C#, and I'm having trouble imagining a concrete situation where structs are really the right choice (at least, I haven't run into one yet.)
So, I turn to the SO world-brain. What are some cases where you actually used a struct in a system where a class wouldn't have worked?
Well a class would still work for it, but an example I could think of is something like a Point. Assuming it is an x and y value, you could use a struct.
struct Point {
int x;
int y;
}
In my mind, I would rather have a more simple representation of a pair of integers than to define a use a class with instantiations when the actual entity does not really have much(or any) behavior.
I used a struct to represent a Geolocation
struct LatLng
{
public decimal Lattitude
{
get;
set;
}
public decimal Longitude
{
get;
set;
}
}
this represents a single entity, for instance I can add 2 LatLng's together or perform other operations on this single entity.
MSDN-struct
The struct type is suitable for
representing lightweight objects such
as Point, Rectangle, and Color.
Although it is possible to represent a
point as a class, a struct is more
efficient in some scenarios. For
example, if you declare an array of
1000 Point objects, you will allocate
additional memory for referencing each
object. In this case, the struct is
less expensive.
Also if you look at primitive types Int32,decimal,double..etc you will notice they are all structs, which allows them to be value types whilst allowing them to implement certain crucial interfaces.
Structs are also typically used in graphics/rendering systems. There are many benefits to making points/vectors structs.
Rico Mariani posted an excellent quiz on value based programming. He discussed many reasons to prefer structs in specific situations, and explained it in detail in his quiz results post.
A Money struct is probably one of the most common, however Phone number or Address are also common.
public struct Money
{
public string Currency { get; set; }
public double Amount { get; set; }
}
public struct PhoneNumber
{
public int Extension { get; set; }
public int RegionCode { get; set; }
//... etc.
}
public struct FullName
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
Keep in mind though that in .NET your structs should not be larger in memory footprint than 16 Bytes, because if they get bigger the CLR has to allocate additional memory.
Also because structs 'live' on the stack (and not the heap as reference types do) you might consider using structs if you need to instantiate a lot of the same types of objects.
The quintessential example is the frameworks nullable types, such as int?. These use structs so they retain the value semantics of an int, yet providing a way to make them null without boxing and turning them into reference types.
You would use a struct when you don't want to pass something by reference. Suppose you have a collection of data, or an object that you wish to pass by value (ie, anything you pass it to is working with its own unique copy, not a reference to the original version) then a struct is the right type to use.
They provide a default implementation for Object.GetHashCode(), so you might want to use a struct instead of a class when the object is a simple collection of non-reference types that you want to use as keys to a dictionary.
They are also useful for PInvoke/interop or low-level networking scenarios where you want precise control over the binary layout of a data structure. (go to www.pinvoke.net for lots of interop code that requires structs)
But really, I never use them myself. Don't sweat not using them.
Basically I try to NOT use them. I find they confuse other developers on the team and thus are not worth the effort. I have only found one case to use it, a custom Enum-like type we use a code generator to produce from XML.
The key for me is to define if I want to keep reference to the same object.
Which makes sence when struct is part of another entity, but does entity itself.
In the example above with LatLong that makes perfect sence, for example. You need to copy values from one object to another, not keep referensing the same object.
I often use structs to represent a domain model value type that might be represented as an enum, but needs an arbitrary unlimited number of discrete values, or I want it to have additional behavior (methods) that you cannot add to an enum... For example, in a recent project many data elements were associated with a specific calendar Month rather than with a date. So I created a CalendarMonth struct that had methods:
static CalendarMonth Parse(DateTime inValue);
static CalendarMonth Parse(string inValue);
and TryParse( ) method,
static bool TryParse(string inValue, out CalendarMonth outVal);
And Properties
int Month { get; set; }
int Year { get; set; }
DateTime StartMonthLocal { get; set; }
DateTime StartMonthUTC{ get; set; }
DateTime EndMonthLocal { get; set; }
DateTime EndMonthUTC { get; set; }
etc.
im not usually concerned with 'data-density' in my business apps. I will typically always use a class unless I specifically want value semantics
this means that i am forseeing a situation where i want to compare two of these things and i want them to show up as the same if they have the same value. With classes this is actually more work because i need to override ==, !=, Equals, and GetHashcode, which even if resharper does it for me, is extra needless code.
So in my mind, always use classes unless you know that you want these things to be compared by value(in this case component value)
So I take it you've never used DateTime (a struct).
I can't believe no one has mentioned XNA: in XNA, almost everything is a struct. So when you do
Matrix rotation = Matrix.CreateRotationZ(Math.PiOver2);
You are really creating a value-type.
This is because, unlike in applications programming, a stall of a few milliseconds while the garbage collector runs is not acceptable (we only get 16.6 ms to render the entire frame!), so we have to avoid allocations as much as possible so the GC doesn't have to run as much.
This is especially true on the XBox 360, where the GC is nowhere near the quality it is on the PC - even an average of one allocation per frame can kill performance!
I have been working in financial institutions where large scale caching and latency requirements was achieved using structs. Basically structs can spare the garbage collector of A LOT of work.
See these examples:
http://00sharp.wordpress.com/2013/07/03/a-case-for-the-struct/
http://00sharp.wordpress.com/2013/07/04/a-case-for-the-structpart-2/
Basically, I use Structs for modeling geometric and mathematical data, or when I want a Value-based data-structure.
The only time I've ever used a struct was when I was building a Fraction struct:
public struct Fraction
{
public int Numerator {get;set;}
public int Denominator {get; set;}
//it then had a bunch of Fraction methods like Reduce, Add, Subtract etc...
}
I felt that it represents a value, just like the built in value types, and therefore coding against it would feel more natural if it behaved like a value type.
I think the .Net Framework is quite real life. See the list under "Structures":
System Namespace
In some performance-critical situations, a struct (a value type and thus allocated from the stack) can be better than a class (a reference type and thus allocated from the heap). Joe Duffy's blog post "A single-word reader/writer spin lock" shows a real-life application of this.
One I've created in the past is StorageCapacity. It represented 0 bytes to N exabytes (could have gone higher to the yottabyte, but exa seemed enough at the time). The struct made sense since I worked for a storage management company. You would think it was fairly simple: a struct with a StorageUnit (enum) and a Quantity (I used decimal). But when you add in conversions, operators, and classes to support formatting, parsing, etc. it adds up.
The abstraction was useful to enable you to take any StorageCapacity and represent it as bytes, kilobytes, etc. without having to multiply or divide by 1024 many times.
I have given my reasons for using structs already elsewhere (When to use struct in C#), and I have used structs for these reasons in real-life projects:
I would choose to use structs for performance reasons if I needed to store a large number of the same item type in an array, which may happen in image processing.
One needs to use structs for passing structured data between C# and C++.
Unless I have a very good reason to use them I try to avoid them.
I know that some people like to use them for implementing value semantics but I find that this behavior is so different from the "normal" assignment behavior of classes (in C#) that one finds oneself running into difficult to trace bugs because one did not remember that the object one was assigning from or to had this behavior because it was implemented as a struct instead of a class. (It has happened to me more than once, so I give this warning since I actually have been burned by the injudicuous use of C# structs.)
I'm not sure how much use this is, but I discovered today that whilst you cannot have instance field intializers in structs, you can in classes.
Hence the following code will give compilation errors, but if you change the "struct" to "class" it compiles.
public struct ServiceType
{
public bool backEnd { get; set; }
public bool frontEnd { get; set; }
public string[] backEndServices = { "Service1", "Service2" };
public string[] frontEndServices = { "Service3", "Service4" };
}
A struct in C# is at its heart nothing more nor less than a bunch of variables stuck together with duct tape. If one wants each variable of a particular type to represent a bunch of independent but related variables (such as the coordinates of a point) stuck together with duct tape, it's often better to use an exposed-field struct than a class, regardless of whether "bunch" means two or twenty. Note that although Microsoft's struct-versus-class advice is fine for data types which encapsulate a single value, it should be considered inapplicable for types whose purpose is to encapsulate independent but related values. The greater the extent to which the variables are independent, the greater the advantages of using an exposed-field struct.
If one wishes to use a class to encapsulate a bunch of independent variables, there are two ways one can do it, neither of which is terribly convenient. One may use an immutable class, in which case any non-null storage location of that class type will encapsulate the values held by the instance identified thereby, and one storage location may be copied to another to make the new one encapsulate those same values. Unfortunately, changing one of the values encapsulated by a storage location will generally require constructing a new instance which is just like the old one except with that value changed. For example, if one has a variable pt of type Immutable3dPoint and one wished to increase pt.X by one, one would have to do something like: pt = new Immutable3dPoint(pt.X+1, pt.Y, pt.Z); Perhaps tolerable if the type only encapsulates three values, but pretty annoying if there very many.
The other class-based approach is to use a mutable class; this generally requires that one ensure that every storage location of the class type holds the only reference anywhere in the universe to an instance of that class. When a storage location is created, one must construct a new instance and store a reference there. If one wishes to copy the values from storage location P to storage location Q, to another, one must copy all the fields or properties from one instance to the other (perhaps by having the type implement a CopyFrom method, and saying Q.CopyFrom(P);. Note that if one instead says Q=P; that may seem to work, but future attempts to modify P will also modify Q and vice versa. Mutable classes may work, and they can at times be efficient, but it's very easy to mess things up.
Exposed-field structures combine the convenient value-copy semantics of immutable classes with the convenient piecewise modifications allowed by mutable classes. Large structures are slower to copy than are references to immutable objects, but the cost of modifying part of an exposed-field structure depends only upon the extent of the modification, rather than upon the overall structure size. By contrast, the cost of changing one piece of data encapsulated in an immutable class type will be proportional to the total class size.

Do enums have a limit of members in C#?

I was wondering if the enum structure type has a limit on its members. I have this very large list of "variables" that I need to store inside an enum or as constants in a class but I finally decided to store them inside a class, however, I'm being a little bit curious about the limit of members of an enum (if any).
So, do enums have a limit on .Net?
Yes. The number of members with distinct values is limited by the underlying type of enum - by default this is Int32, so you can get that many different members (2^32 - I find it hard that you will reach that limit), but you can explicitly specify the underlying type like this:
enum Foo : byte { /* can have at most 256 members with distinct values */ }
Of course, you can have as many members as you want if they all have the same value:
enum { A, B = A, C = A, ... }
In either case, there is probably some implementation-defined limit in C# compiler, but I would expect it to be MIN(range-of-Int32, free-memory), rather than a hard limit.
Due to a limit in the PE file format, you probably can't exceed some 100,000,000 values. Maybe more, maybe less, but definitely not a problem.
From the C# Language Specification 3.0, 1.10:
An enum type’s storage format and
range of possible values are
determined by its underlying type.
While I'm not 100% sure I would expect Microsoft C# compiler only allowing non-negative enum values, so if the underlying type is an Int32 (it is, by default) then I would expect about 2^31 possible values, but this is an implementation detail as it is not specified. If you need more than that, you're probably doing something wrong.
You could theoretically use int64 as your base type in the enum and get 2^63 possible entries. Others have given you excellent answers on this.
I think there is a second implied question of should you use an enum for something with a huge number of items. This actually directly applies to your project in many ways.
One of the biggest considerations would be long term maintainability. Do you think the company will ever change the list of values you are using? If so will there need to be backward compatibility to previous lists? How significant a problem could this be? In general, the larger the number of members in an enum correlates to a higher probability the list will need to be modified at some future date.
Enums are great for many things. They are clean, quick and simple to implement. They work great with IntelliSense and make the next programmer's job easier, especially if the names are clear, concise and if needed, well documented.
The problem is an enumeration also comes with drawbacks. They can be problematic if they ever need to be changed, especially if the classes using them are being persisted to storage.
In most cases enums are persisted to storage as their underlying values, not as their friendly names.
enum InsuranceClass
{
Home, //value = 0 (int32)
Vehicle, //value = 1 (int32)
Life, //value = 2 (int32)
Health //value = 3 (int32)
}
In this example the value InsuranceClass.Life would get persisted as a number 2.
If another programmer makes a small change to the system and adds Pet to the enum like this;
enum InsuranceClass
{
Home, //value = 0 (int32)
Vehicle, //value = 1 (int32)
Pet, //value = 2 (int32)
Life, //value = 3 (int32)
Health //value = 4 (int32)
}
All of the data coming out of the storage will now show the Life policies as Pet policies. This is an extremely easy mistake to make and can introduce bugs that are difficult to track down.
The second major issue with enums is that every change of the data will require you to rebuild and redeploy your program. This can cause varying degrees of pain. On a web server that may not be a big issue, but if this is an app used on 5000 desktop systems you have an entirely different cost to redeploy your minor list change.
If your list is likely to change periodically you should really consider a system that stores that list in some other form, most likely outside your code. Databases were specifically designed for this scenario or even a simple config file could be used (not the preffered solution). Smart planning for changes can reduce or avoid the problems associated with rebuilding and redeploying your software.
This is not a suggestion to prematurely optimize your system for the possibility of change, but more a suggestion to structure the code so that a likely change in the future doesn't create a major problem. Different situations will require difference decisions.
Here are my rough rules of thumb for the use of enums;
Use them to classify and define other data, but not as data
themselves. To be clearer, I would use InsuranceClass.Life to
determine how the other data in a class should be used, but I would
not make the underlying value of {pseudocode} InsuranceClass.Life = $653.00 and
use the value itself in calculations. Enums are not constants. Doing
this creates confusion.
Use enums when the enum list is unlikely to change. Enums are great
for fundamental concepts but poor for constantly changing ideas.
When you create an enumeration this is a contract with future
programmers that you want to avoid breaking.
If you must change an enum, then have a rule everyone follows that
you add to the end, not the middle. The alternative is that you
define specific values to each enum and never change those. The
point is that you are unlikely to know how others are using your
enumerations underlying values and changing them can cause misery for anyone
else using your code. This is an order of magnitude more important
for any system that persists data.
The corollary to #2 and #3 is to never delete a member of an enum.
There are specific circles of hell for programmers who do this in a codebase used by others.
Hopefully that expanded on the answers in a helpful way.

Which is faster/more efficient: Dictionary<string,object> or Dictionary<enum,object>?

Are enum types faster/more efficient than string types when used as dictionary keys?
IDictionary<string,object> or IDictionary<enum,object>
As a matter of fact, which data type is most suitable as a dictionary key and why?
Consider the following: NOTE: Only 5 properties for simplicity
struct MyKeys
{
public string Incomplete = "IN";
public string Submitted = "SU";
public string Processing="PR";
public string Completed = "CO";
public string Closed = "CL";
}
and
enum MyKeys
{
Incomplete,
Submitted,
Processing,
Completed,
Closed
}
Which of the above will be better if used as keys in a dictionary!
Certainly the enum version is better (when both are applicable and make sense, of course). Not just for performance (it can be better or worse, see Rashack's very good comment) as it's checked compile time and results in cleaner code.
You can circumvent the comparer issue by using Dictionary<int, object> and casting enum keys to ints or specifying a custom comparer.
I think you should start by focusing on correctness. This is far more important than the minimal difference between the minor performance differences that may occur within your program. In this case I would focus on the proper representation of your types (enum appears to be best). Then later on profile your application and if there is a issue, then and only then should you fix it.
Making code faster later in the process is typically a straight forward process. Take the link that skolima provided. If you had chosen enum, it would have been a roughly 10 minute fix to remove a potential performance problem in your application. I want to stress the word potential here. This was definitely a problem for NHibernate but as to whether or not it would be a problem for your program would be solely determined by the uses.
On the other hand, making code more correct later in the process tends to be more difficult. In a large enough problem you'll find that people start taking dependencies on the side effects of the previous bad behavior. This can make correcting code without breaking other components challenging.
Use enum to get cleaner and nicer code, but remember to provide a custom comparer if you are concerned with performance: http://ayende.com/Blog/archive/2009/02/21/dictionaryltenumtgt-puzzler.aspx .
I would guess that the enum version is faster. Under the hood the dictionary references everything by hashcode. My guess is that it is slower to generate the hashcode for a string. However, this is probably negligibly slower, and is most certainly faster than anything like a string compare. I agree with the other posters who said that an enum is cleaner.

Have trivial properties ever saved your bacon?

There's a lot of advice out there that you shouldn't expose your fields publically, and instead use trivial properties. I see it over & over.
I understand the arguments, but I don't think it's good advice in most cases.
Does anyone have an example of a time when it really mattered? When writing a trivial property made something important possible in the future (or when failing to use one got them in to real trouble)?
EDIT: The DataBinding argument is correct, but not very interesting. It's a bug in the DataBinding code that it won't accept public fields. So, we have to write properties to work around that bug, not because properties are a wise class design choice.
EDIT: To be clear, I'm looking for real-world examples, not theory. A time when it really mattered.
EDIT: The ability to set a breakpoint on the setter seems valuable. Designing my code for the debugger is unfortunate: I'd rather the debugger get smarter, but given the debugger we have, I'll take this ability. Good stuff.
It may be hard to make code work in an uncertain future, but that's no excuse to be lazy. Coding a property over a field is convention and it's pragmatic. Call it defensive programming.
Other people will also complain that there's a speed issue, but the JIT'er is smart enough to make it just about as fast as exposing a public field. Fast enough that I'll never notice.
Some non-trivial things that come to mind
A public field is totally public, you can not impose read-only or write-only semantics
A property can have have different get versus set accessibility (e.g. public get, internal set)
You can not override a field, but you can have virtual properties.
Your class has no control over the public field
Your class can control the property. It can limit setting to allowable range of values, flag that the state was changed, and even lazy-load the value.
Reflection semantics differ. A public field is not a property.
No databinding, as others point out. (It's only a bug to you. - I can understand Why .net framework designers do not support patterns they are not in favour of.)
You can not put a field on an interface, but you can put a property on an interface.
Your property doesn't even need to store data. You can create a facade and dispatch to a contained object.
You only type an extra 13 characters for correctness. That hardly seems like speculative generality. There is a semantic difference, and if nothing else, a property has a different semantic meaning and is far more flexible than a public field.
public string Name { get; set; }
public string name;
I do recall one time when first using .net I coded a few classes as just fields, and then I needed to have them as properties for some reason, and it was a complete waste of time when I could have just done it right the first time.
So what reasons do you have for not following convention? Why do you feel the need to swim upstream? What has it saved you by not doing this?
I've had a trivial property save me a couple of times when debugging. .Net doesn't support the concept of a data break point (read or write). Occasionally when debugging a very complex scenario it was important to track read/writes to a particular property. This is easy with a property but impossible with a field.
If you're not working in a production environment, it's simple to refactor a field -> property for the purpose of debugging. Occasionally though you hit bugs that only reproduce in a production environment that is difficult to patch with a new binary. A property can save you here.
It's a fairly constrained scenario though.
I used to think the same thing, Jay. Why use a property if it's only there to provide direct access to a private member? If you can describe it as an autoproperty, having a property at all rather than a field seemed kind of silly. Even if you ever need to change the implementation, you could always just refactor into a real property later and any dependent code would still work, right?. Well, maybe not.
You see, I've recently seen the light on trivial properties, so maybe now I can help you do the same.
What finally convinced me was the fairly obvious point (in retrospect) that properties in .Net are just syntactic sugar for getter and setter methods, and those methods have a different name from the property itself. Code in the same assembly will still work, because you have to recompile it at the same time anyway. But any code in a different assembly that links to yours will fail if you refactor a field to a property, unless it's recompiled against your new version at the same time. If it's a property from the get-go, everything is still good.
I'll answer your question with another one: have you ever really benefited from not making all your types and members public? I suspect I haven't directly prevented any bugs by doing so. However, I've encapsulated my types properly, only exposing what's meant to be exposed. Properties are similar - good design more than anything else. I think of properties as conceptually different from fields; they're part of the contract rather than being fundamentally part of the implementation. Thinking about them as properties rather than fields helps me to think more clearly about my design, leading to better code.
Oh, and I've benefited occasionally from not breaking source compatibility, being able to set breakpoints, log access etc.
Part of the idea is that those properties may not be trivial in the future - if you bound external code to a field and later wanted to wrap that in a property, all of the dependent code would have to change, and you may not be able to do that, especially in the case where you are a control designer or have libraries that you can't control, etc.
Not to mention there are certain .NET practices that will not allow you to use a field - databinding particularly.
I am sure there are other good reasons as well. Why does it matter to you? Use an automatic property and be done with it. Seems like something not worth being concerned about to me...
It's much easier to debug a problem involving a field if it is wrapped by a property accessor. Placing breakpoints in the accessor can quite quickly help with finding re-entrancy and other issues that otherwise might not be caught. By marshaling all access to the field through an accessor, you can ascertain exactly who is changing what and when.
In .NET, from my understanding, you cannot databind to public fields; but only to properties. Thus, if you want to do databinding, you have no choice.
I once had fields that I wanted to expose from a windows from project which allowed the stats for the program (TotalItems and SuccessfulItems).
Later I decided to display the stats on the form and was able to add a call in the setter that updated the display when the property changed.
Obviously, if you're not creating a shared class library, and you're not using DataBinding, then using a field will cause you no problems whatsoever.
But if you're creating a shared class library, you'd be foolish IMHO to do otherwise than follow the guidelines, for the usual three reasons:
consumers of your shared class library may want to use DataBinding.
consumers of your shared class might want binary compatibility, which is not possible if you switch from a field to a property.
the principal of least surprise implies you should be consistent with other shared class libraries including the .NET Framework itself.
IMHO there is no such thing as a trivial property as people have been calling them. Via the way things such as databinding work, Microsoft has implied that any bit of data that is a part of the public interface of an object should be a property. I don't think they meant it merely to be a convention like it is in some other languages where property syntax is more about convention and convenience.
A more interesting question may be: "When should I use a public field instead of a property", or "When has a public field instead of a public property saved your bacon?"
Fields which are of structure types allow direct access to the members thereof, while properties of such types do not. Consequently, if Thing.Boz were a field of type Point, code which wants to modify its X value could simply say Thing.Boz.X += 5;; if Thing.Boz were a mutable property, it would be necessary to use var tmp = Thing.Boz; tmp.X += 5; Thing.Boz = tmp;. The ability to write things more cleanly with the exposed field is often, but not always, a blessing.
If it will always be possible for Boz to be a field, modifying its members directly will be cleaner, faster, and better than copying it to a temporary variable, modifying that, and copying it back. If the type of Boz exposes its mutable fields directly (as structures should) rather than wrapping them in trivial wrappers, it will also be possible to use things like Interlocked methods on them--something that's simply impossible with properties. There's really only one disadvantage to using fields in that way: if it's ever necessary to replace the field with a property, code which relied upon the thing being a field will break, and may be hard to fix.
In short, I would posit that in cases where one isn't concerned about being able to swap in different versions of code without having to recompile any consumers, the biggest effect of using properties rather than fields is to prevent consumers of the code from writing code which would take advantage of (and rely upon) the semantics of exposed fields which are of structure types.
Incidentally, an alternative to exposing a field of a structure type would be to expose an ActOnXXX method. For example:
delegate void ActionByRef<T1>(ref T1 p1);
delegate void ActionByRef<T1,T2>(ref T1 p1, ref T2 p2);
delegate void ActionByRef<T1,T2,T3>(ref T1 p1, ref T2 p2, ref T3 p3);
// Method within the type that defines property `Boz`
void ActOnBoz<T1>(ActionByRef<Point, T1> proc, ref T1 p1)
{
proc(ref _Boz, ref p1); // _Boz is the private backing field
}
Code which wanted to add some local variable q to Thing.Boz.X could call Thing.ActOnBoz((ref Point pt, ref int x) => {pt.X += x;}, ref q); and have the action performed directly on Thing._Boz, even though the field is not exposed.

Categories