|
Tom Archer wrote:
Please don't take my correction as putting your article down
Never took it that way, I'm always open and greatful for constructive critisism, specially from people who know what they're talking about.
Tom Archer wrote:
However, your wording on the foreach/IEnumerable does state that you must implement IEnumerable (as opposed to stating that it is one way)
That's why I said that the item doesn't show the whole picture. As soon as a pending update gets posted I will update the collection-related items to show the a more complete view and some optimizations that can be done when defining and implementing collections and enumerators.
Tom Archer wrote:
Have you read the second edition?
That's the one I was refering to. Great book, one of three that I currently consider must-read C# books.
Eddie Velasquez: A Squeezed Devil
Checkout General Guidelines for C# Class Implementation
|
|
|
|
|
Eddie Velasquez wrote:
That's the one I was refering to. Great book, one of three that I currently consider must-read C# books.
And the other two are? I'm always looking for a good book.
Jerry
|
|
|
|
|
I know this is off topic, but like 'patnsnaudy', I would also like to see a list of best-of-breed C# books...
Can you list your favorites and mention why they're on your list (and what kind of reader you think they would be most appropriate for)?
Gilad
|
|
|
|
|
Should not we getting away from adding the "m_" prefix to class member variables, as for Microsoft recommendation? I spent years doing that in my MFC code and loved the fact that all MFC programmers did it too because it was easier to read MFC code, but ever since I started writing C# I don't do it anymore to make sure my code complies with the new guidelines. However if I write new MFC code I will definately use the old conventions.
|
|
|
|
|
Hello Carlos,
What's wrong with m_ ? I use it in my C# and MC++ programs, as a sort of hangover from MFC I guess. But what is the newly recommended method? Just use a normal word with the first letter capitalized???
Nish
Regards,
Nish
Native CPian.
Born and brought up on CP.
With the CP blood in him.
|
|
|
|
|
I don't think Nish that is a matter of right or wrong. I myself don't see anything wrong with the old method. I made the comment because if an article talks about Guidelines, then it follows that the article itself should follow the "Guidelines". According to Microsoft you should use Pascal or Camel casing when doing .NET. Hungarian notation and prefixes in general are deprecated.
|
|
|
|
|
Carlos H. Perez wrote:
According to Microsoft you should use Pascal or Camel casing when doing .NET. Hungarian notation and prefixes in general are deprecated.
Thanks for the info, Carlos!
Nish
Regards,
Nish
Native CPian.
Born and brought up on CP.
With the CP blood in him.
|
|
|
|
|
Carlos H. Perez wrote:
According to Microsoft you should use Pascal or Camel casing when doing .NET. Hungarian notation and prefixes in general are deprecated.
Well, I believe that .NET's naming convention refers more to the public interface instead of the internals of classes. I don't see why I should drop the "m_" prefix for private data members (and "s_" for private static data members) I don't use hungarian notation in my C# code and only use a "type intention" subset for my C++ code.
Eddie Velasquez: A Squeezed Devil (Don't you just love that anagram craze?)
|
|
|
|
|
Eddie Velasquez wrote:
Well, I believe that .NET's naming convention refers more to the public interface instead of the internals of classes.
yes, the Microsoft guidelines as written in the case guidelines only refer to public and protected members, not private.
Microsoft isn't claiming any real standards for naming private areas of a class.
The reason for this is a very good one. You'll notice that the public naming conventions they mention are very language agnostic. I can't think of any .net-compatible language that couldn't support them.
Private parts of a class can become very language specific, and as such, there is no good way to provide are "works for everybody" guideline.
They can't really suggest using case differences or non-alphanumeric characters, because some languages just don't support that kind of thing.
|
|
|
|
|
The articles says that you should implement operator == and != by forwarding to Equals(). If you're doing a reference type, that's fine, but if you're doing a value type, you want to do the opposite. Equals() takes an object as parameter, so using it on a value type requires boxing.
The overloaded operators, on the other hand, don't require boxing, but if you forward them to Equals(), you'll add in a superfluous box/unbox pair.
|
|
|
|
|
Of course you're right, I didn't realize it but it's quite obvious. I'll fix the article. Thanks
Eddie Velasquez: A Squeezed Devil (Don't you just love that anagram craze?)
Checkout GUIDGen.NET
|
|
|
|
|
There really is a huge schism in the community with this whole concept.
After reading a lot of opinions, talking to developers and the c# language designers, and having a long discussion on it in the aspngcs list on aspfriends.com, I kinda came up with these guidelines...
for reference types:
if you want to compare equality based on some properties of that object...
DO override Equals and GetHashCode. this is for hashing, sorting, and testing equality of the values. The Equals will most likely call Equals on properties that are reference types, and == on properties that are value types.
DO NOT override the == and != operators. these should always stay as testing referential equality. It is expected that == is the same as calling Object.ReferenceEquals()
for value types:
you are correct, override == ( and implement != as calling !(==) ), and then implement Equals as doing some type checking and calling ==.
for those of you wanting to implement a ValueComparedReferenceType using these guidlines, here's some code I whipped up a while ago...
public class MyType : ValueComparedReferenceType {
public String Identifier = String.Empty;
protected override Boolean ValueEquals( Object o ) {
MyType other = (MyType)o;
return ( this.Identifier == other.Identifier );
}
protected override Int32 GetValueHashCode() {
return Identifier.GetHashCode();
}
}
public abstract class ValueComparedReferenceType {
protected abstract Boolean ValueEquals( Object o );
protected abstract Int32 GetValueHashCode();
public override Int32 GetHashCode() {
return this.GetValueHashCode();
}
public static new Boolean Equals( Object o1, Object o2 ) {
if( o1 == null ) {
return ( o2 == null );
} else {
return o1.Equals( o2 );
}
}
public override Boolean Equals(object o) {
if (o == null) return false;
if ( Object.ReferenceEquals( o, this ) ) return true;
if ( o.GetType() != this.GetType() ) return false;
return this.ValueEquals( o );
}
}
|
|
|
|
|
heh
eric, i didn't even notice it was you that started this thread.
now i feel foolish.
I got my info from the discussion we had a while ago on aspngcs.
tell me if i'm wrong anywhere there.
|
|
|
|
|
I think I'd phrase this somewhat differently.
The real question I have is whether there's a meaningful concept of equality for a class or not.
If there is such a concept, then my recommendation is that it be implemented consistently, which means doing Equals(), HashCode(), and the comparison operators.
While this does make it harder to get reference equality (you have to cast to object), I think having operator== mean reference comparison for *some* object and not for others is far worse.
If there isn't a good concept of equality but there is a concept of primary key, I think that enable hash table usage by implementing just Equals() and GetHashCode() is probably fine.
|
|
|
|
|
Eric Gunnerson (msft) wrote:
The real question I have is whether there's a meaningful concept of equality for a class or not.If there is such a concept, then my recommendation is that it be implemented consistently, which means doing Equals(), HashCode(), and the comparison operators.
I don't understand your question, because item 4 states: "Implement Object.GetHashCode() and Object.Equals() if comparing objects makes sense.". So I think my point is exactly what your saying (if I'm interpreting your post correctly)
Eddie Velasquez: A Squeezed Devil (Don't you just love that anagram craze?)
Checkout GUIDGen.NET
|
|
|
|
|
|
Did you miss item 19? It's all about FxCop!
Eddie Velasquez: A Squeezed Devil (Don't you just love that anagram craze?)
Checkout GUIDGen.NET
|
|
|
|
|
I am sorry. I actually wondered how you missed that. Any way my post count is increased
|
|
|
|
|
This looks like a great set of rules to follow, it has all sorts of forethought in it. But - there are some error handling idioms in C# that I think should be part of the list.
For one, I would always wrap potential failures in try blocks with finally blocks to ensure releasing any system resources (even if you don't catch the potential exceptions). To make this easier, classes that allocate/lock resources should implement IDisposable so that they can be used with the short-cut "using" statement/block.
There should also be guidelines to generally inheriting from System.ApplicationException for your own exceptions. Also, you should probably split out catching exception base classes System.ApplicationException and System.SystemException - and only the main application should ever catch the most generic System.Exception.
Of course, you should usually look for the most specific exceptions - and if you don't know what to do with the exceptions, don't catch it and let the higher level code deal with it.
Just a few thoughts.
Dale Thompson
|
|
|
|
|
Dale Thompson wrote:
But - there are some error handling idioms in C# that I think should be part of the list.
There's a bunch of things that are still missing and I will get to them as soon as I have some free time.
Thanks for your input, correct exception handling is unavoidable in .NET and it deserves a to be part of this list.
Eddie Velasquez: A Squeezed Devil (Don't you just love that anagram craze?)
Checkout GUIDGen.NET
|
|
|
|
|
I look forward to seeing the update - thanks for putting it together.
Dale Thompson
|
|
|
|
|
Another little tweak. When rethrowing an exception you should typically do one of two things:
1) Wrap it a more specific exception - which you have shown, or;
2) Rethrow it directly, which means using just "throw;" with no argument.
I can't think of a good reason to rethrow exactly the object you just caught as is currently shown.
regards,
--
-Blake (com/bcdev/blake)
|
|
|
|
|
Blake Coverett wrote:
I can't think of a good reason to rethrow exactly the object you just caught as is currently shown.
Me neither, it's a typo.
Eddie Velasquez: A Squeezed Devil (Don't you just love that anagram craze?)
Checkout GUIDGen.NET
|
|
|
|
|
Well,great art' indeed ,However it show that the sharp
isnt sharp somehow.the ToString overide function shows
that somethign that should have done by Microsoft wasnt done at all and that ,show how thay threat there belivers.
|
|
|
|
|
Ok, WTF are you talking about?
The ToString was left as an override because it is used in many places to provide a MEANINGFUL text representation. For example if I create a class I can add an instance of it to a listbox and so long as I haven't set some certain properties on the listbox it shows what ToString() outputs (those properties are DisplayMember and ValueMember).
And the remark about Microsoft no longer applies, C# is an EMCA standard now and is out of MS' hands.
James
Simplicity Rules!
|
|
|
|