|
Nemanja Trifunovic wrote:
I would say: interfaces of all the public classes should be CLS compliant.
Well, the term interface has already a well defined meaning in C#. The item should probably be refrased as "All classes, structs and interfaces should be CLS compliant."
All of my opinions are correct, even when reality makes the mistake of disagreeing with me.
ASP.NET can never fail as working with it is like fitting bras to supermodels - it's one pleasure after the next - David Wulff
|
|
|
|
|
FYI:
If after your using statements you add the following line:
[assembly:CLSCompliant(true)]
then when you compile your code the compiler will insure that all of your code is CLS compliant.
|
|
|
|
|
That's exacly what item 8 states. What I was discussing was that Nemanja's use of the word "interface" in a generic sense is somewhat confusing because "interface" already has a well defined meaning in C#.
There are only 10 kind of people in the world: those who understand binary and those who don't.
|
|
|
|
|
How about "all types should be CLS-compliant"? (since a "type" is considered any class, struct, or interface, in C#)
|
|
|
|
|
dacris wrote:
How about "all types should be CLS-compliant"? (since a "type" is considered any class, struct, or interface, in C#)
I agree
The nice thing about C++ is that only your friends can handle your private parts.
|
|
|
|
|
I haven't had time to read through the entire article, but at a glance it looks very good. However, #13 is in error. In that bullet, you state that "For a 'collection' class to be used in a foreach loop it must implement IEnumerable."
Here's the syntax for the foreach operator:
<br />
foreach (type-identifier in expression) <br />
embedded-statement<br />
Technically, the foreach operator will work on expression as long as expression is said to be a collection type. This means that expression must either implement IEnumerable (as you mentioned) or implement the collection pattern, which is defined as follows:
* expression must contain a public instance method called GetEnumerator that takes no parameters and returns a struct, class or interface.
* The type returned from the GetEnumerator method must contain a public instance method called MoveNext that takes no parameters and returns a bool value.
* The type returned from the GetEnumerator method must contain a public instance method called Current that takes no parameters and returns a reference type.
In case you're interested, 'Inside C#' has a full chapter on enumeration which goes into all sorts of various ways of implementing enumerators including creating versioned enumerators, combining the IEnumerable and IEnumerator interfaces, protecting data while allowing enumeration, various performance issues and using a mutator interface to modify collected value types.
Cheers,
Tom Archer
Author - Inside C#, Visual C++.NET Bible
Please remember to keep this for tax purposes.
|
|
|
|
|
Tom Archer wrote:
haven't had time to read through the entire article, but at a glance it looks very good
Thanks
Tom Archer wrote:
However, #13 is in error. In that bullet, you state that "For a 'collection' class to be used in a foreach loop it must implement IEnumerable."
Well, I wouldn't say it's in error, it just doesn't show the whole picture. This article is just a list of reminders of "what should be done" while I learn C#. Trying to explain all the "whys" is out of the scope of the article and out of my current knowledge of C#. There are plenty of great C# books out there that anybody could (and should!) get to reach C# mastery.
Tom Archer wrote:
'Inside C#' has a full chapter on enumeration which goes into all sorts of various ways of implementing enumerators
I've read 'Inside C#' and I must say it's a recommended reading.
Eddie Velasquez: A Squeezed Devil
Checkout General Guidelines for C# Class Implementation
|
|
|
|
|
Please don't take my correction as putting your article down as I think your article is a very good starting point for many people that are new to C#. However, your wording on the foreach/IEnumerable does state that you must implement IEnumerable (as opposed to stating that it is one way).
Thanks for the kind words on the book. Have you read the second edition? It has a lot of depth on issues such as the aforementioned IEnumerable interface.
Cheers,
Tom Archer
Author - Inside C#, Visual C++.NET Bible
Please remember to keep this for tax purposes.
|
|
|
|
|
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
|
|
|
|