Helpful IDE's aren't always a good thing

Published July 01, 2006
Advertisement
I've spent most of the day fighting with VC# 2005 and its insistence on re-formatting my C# code.

After getting close to hunting down the C# team at MS and inflicting much pain I realised there are menu options to customize it. Which is nice as it mostly suits my style now... but still, its got annoying tendencies.

The formatting of statements (adding spaces after "," and before "()" etc..) seems to only be done when I type a ";". Makes sense but if I go back and edit a function call it doesn't re-fix my formatting... why?!

Intellisense can be great, but its been a bit of a shock to have context menus popping up every few characters. I used to rely on intellisense to navigate around Java's libraries, but with DX/C++ I've gotten used to either non-existant or very random/sparse intellisense.

I'm still trying to work my way through it (its fun to be a n00b again), but two questions:

(1) How do I set up const references? In C++ I might have void MyFunc( const type& t );, but I keep getting C# moan if I drop const into a parameter list. I get the whole ref keyword for passing by reference, but I want to have some constant parameters [oh]

(2) How do I get static declarations in a method? I wanted a simple counter in a recursive function, and in C++ I could do static int count = 1; and then have ++count; (etc...) C# doesn't seem to like that.


Oh, and in closing... congrats to Portugal - I now get to listen to the locals smashing up stuff (yeah, they've started already), fighting and generally shouting a whole lot [rolleyes]. Gotta love some of the "supporters"/"fans" of England.
0 likes 15 comments

Comments

HopeDagger
Yes, the auto-formatting stuff is taken from the VB(.NET) IDEs of forcing formatting down your throat with an iron 20-foot rod. And yes, I hate it too. Especially when you paste in some copied code and it reformats it. *shudder*

Quote:(1) How do I set up const references?


To my knowledge, you can't.

Quote:(2) How do I get static declarations in a method? I wanted a simple counter in a recursive function, and in C++ I could do static int count = 1; and then have ++count; (etc...) C# doesn't seem to like that.


No, C# doesn't allow this either. These nuances are a little annoying at first, but you'll come around. They always do. [smile]


(Any .NET gurus feel free to correct me, but I'm reasonably sure on my pessimistic answers [sad])
July 01, 2006 03:09 PM
jollyjeffers
... and there I was hoping it was my stupidity that I couldn't work out const references/statics...

I like marking params as constant - its a nice way of making a compiler-enforced contract that you're not going to be messing with them.

So if you want to send in a primitive type (e.g. int) you either pass it as ( ref int X ) and you'll avoid a by-val copy operation but the caller risks having the variable messed with. The by-val copy operation for a primitive isn't bad, but could be nasty if you've got a struct.

If you're passing in a class then they're by-reference anyway, which means the function body can (within reason) do whatever the hell it wants with it. You can't pass it in as const to enforce it as being informational only.

How crap.

Jack
July 01, 2006 04:19 PM
Scet
Quote:Original post by jollyjeffers

So if you want to send in a primitive type (e.g. int) you either pass it as ( ref int X ) and you'll avoid a by-val copy operation but the caller risks having the variable messed with. The by-val copy operation for a primitive isn't bad, but could be nasty if you've got a struct.

How crap.


It's not crap, you can't do those things because you don't need to. If you want a static varible just create it within the class, after all everything has to be in a class anyway, plus that'll give the other members of the class access to it instead of just one function.

Also there's more than just by-val and by reference, look up the in and out keywords.

When I started using C# I really wanted to go back to C++, but I hung in there and am glad I did. I tried to do some C++ stuff a while ago and got totally pissed at the header/lib/linker nonsense [smile]. C backwards compatibility is crap.

Edit: Oh yeah and give SharpDevelop a shot if you find VC# a royal pain, I know I did(it kept freezing on me).
July 01, 2006 05:13 PM
jollyjeffers
Quote:Original post by Scet
It's not crap, you can't do those things because you don't need to.
Good point. I figured I'd probably end up trying to write C# the same way I write C++, but didn't think I'd trip myself up so quickly [headshake]

I tend to write a lot of procedural C++ these days, so I'm a little rusty on the OOP way of thinking.

Quote:Original post by Scet
Also there's more than just by-val and by reference, look up the in and out keywords.
Yup, I've seen those but not checked them out properly yet. There are a couple of other keywords (checked, unchecked and yield to name a few) that I've not quite got my head around yet.

Quote:Original post by Scet
Oh yeah and give SharpDevelop a shot if you find VC# a royal pain, I know I did(it kept freezing on me).
I'm not getting the stability/performance problems that lots of people complain about - I think its the exactly-as-intended characteristics that rub me up the wrong way.

If I can't get used to it then I'll follow up on your recommendation.

Cheers,
Jack

July 01, 2006 05:26 PM
ET3D
AFAIK the 'in' keyword is not valid for parameter passing. You can only use 'ref', 'out' and 'param' (see here).

Yes, having a qualifier for input-only would be nice. Why don't you suggest it somewhere, like in the private C# newsgroup?

As for using static variable defined in functions, it's one of the things that's good that they got rid of. It can be useful for debugging, but it's problematic, since it defines variables that have no specific time of death, and that are global in terms of life but limited in access scope to one function.
July 02, 2006 02:32 AM
remigius
Quote:Yes, having a qualifier for input-only would be nice.


Nice for annotation, but not necessarily useful. Value-types are passed by-value unless otherwise specified (not sure if you can do ref int, though that should work due to boxing) and strings are immutable. So this behaviour already makes those input-only, since modifying them in your method won't affect the original variable in the code calling the method.

Specifying an object as input-only can be a bit harder to get around (though you may specify fields and properties of an object as read-only). Modifying an object 'externally' however should be avoided in OO design, from my hazy recollection of my OO courses anyway. If a method modifies an object (engine.Move(object, x, y) for example), then such a method should typically be a member function of the class anyway (object.Move(x,y)). Of course there are exceptions to this design guideline that make perfect sense, this should hold true but in general.

Hope this helps :)
July 02, 2006 03:45 AM
jollyjeffers
Thanks for the replies!

Quote:Yes, having a qualifier for input-only would be nice. Why don't you suggest it somewhere, like in the private C# newsgroup?
Good idea. Although I'm not sure whether such an "obvious" change to the language could be brought about by a single person [oh]

Quote:As for using static variable defined in functions, it's one of the things that's good that they got rid of.
Agreed, I found out they were gone in C# by trying to use them for debugging/testing - not a legitimate part of my program.

Quote:Nice for annotation, but not necessarily useful.
Its a form of design by contract. Its a way of giving the compiler extra information/context so it can catch more mistakes/bugs for you.

Example:

class Employee { /* .... */ };
public void PrintEmployeeDetailsToConsole( Employee e )
{
    Console.writeLine( "Employee name is '{0} {1}'.", e.firstName, e.secondName );
}


Now, given that we're passing by-reference here if I ONLY know the declaration for PrintEmployeeDetailsToConsole() I have no guarantees as to what state "e" will be once it finishes. A good Employee design should guarantee its in a consistent state - but that does not mean the SAME state.

Based on the name I can guess it's just going to be reading information and pushing it to the console. If I could declare it as ( const Employee e ) like in C++ I can GUARANTEE that its only going to be reading and printing.

Similarly as the implementer of the method, if I make that declaration but later (say its a bigger/complex method) unintentionally misuse the class and start changing stuff then the compiler will start screaming and shouting at me. I know near-enough immediately that there is a bug.

I have actually had numerous problems like this before - simple log-file/debug code that by-design just prints data out but in fact unintentionally changed it. Thus I spent hours trying to find which bit of my (actually correct) algorithm was broken... [rolleyes]

So, does C# offer me anything to solve this?

Jack
July 02, 2006 08:36 AM
Muhammad Haggag
Regarding const-correctness:

I personally believe const-correctness is a great concept. It's very useful in general (regardless of a specific programming language), and very useful in the context of C++ specifically (say: without it, you wouldn't be able to pass a string literal to a function taking a std::string by reference).

Raymond Chen seems to indicate that the reason they dropped const out of .NET is due to compatibility with Visual Basic. Visual Basic doesn't have const, he says, and thus it'd break if it interacted with any code that has const. I think that reason is crap. Visual Basic.NET is already very different from Visual Basic, and it wouldn't have hurt much to add const to it.

It should be mentioned that many people regard the C++ implementation of const-correctness as broken, for one of, or both of the following:
1) It can be cast away, using const_cast. They say that this means const doesn't guarantee anything. Walter Bright (of D fame), seems to believe so--these people prefer consulting the documentation about whether the function modifies the object or not.

I believe this argument is nonesense. const_cast is there, yes, but it's only there for the cases when you're dealing with a broken library -- a library whose interface isn't const-correct, even though the underlying implementation is. I've been working with MsgConnect a lot recently, and it's notoriously messed up in the const-correctness department. Almost all functions take read-only C-strings, but they're not marked as const.

In short, const_cast is not there so that you can modify a const object. It's there so that a const object can be passed to a function that we know (through documentation) doesn't modify the object, but has a non-const interface.

2) Non-constness is the default. If you think about it, it actually makes much more sense to have constness be the default, and mark parameters that change as such. The way I see it, though, this isn't solved by just dropping const, but by making const the default and adding a new keword like "mutable" or something in front of parameters that will be changed.

This is one of the things I miss in C#. When actually working on large projects with C#, I often have to double-check the documentation before every user-written function I call to make sure it doesn't modify anything, because it's not apparent from its declarator what it does modify and what it doesn't.
July 02, 2006 02:32 PM
jollyjeffers
Some very good points there Muhammad - can't find fault in them [smile]

Will have to read those MSDN blogs properly tomorrow, they look interesting.

as for const_cast - yes it can be dangerous, but so can the other casts... and lets not get started on the amount of crazy stuff you can do with pointers [lol]. Using it against const-correctness is just silly given how easy it is to hurt yourself using C/C++ if you're not careful.

Cheers,
Jack
July 02, 2006 04:04 PM
remigius
An alternative might be to use properties for all publicly available variables in a C# class. This offers the possibility to put breakpoints into the setters, so your could check at runtime if a value is changed. If you're really worried about const correctness, you could create a wrapper which only exposes the getters on the properties.

A somewhat more elegant way to do this would be to just define an interface exposing the read-only properties of your object and having your actual data class implement this interface. You can then use the interface as the parameter type and pass in the object without any casting or further overhead. This might be some more work than using the const modifier, but it could give you more finegrained control over which properties of an object should be read-only to some particular method.
July 02, 2006 04:10 PM
remigius
Hmm, something seems to have gone wrong with my post, instead of mine Jack's popped up instead. To cut a long story short, an option to solve this would be to define an interface in which the properties of an object are defined as read-only and using this interface as the parameter type for the method. Like this:

[source lang=c#]
interface IReadOnlyEmployee
{
    string FirstName { get; }
}

class Employee : IReadOnlyEmployee
{
    private string firstName;

    public string FirstName
    {
        get { return firstName; }
        set { firstName = value; }
    }
}

class EmployeeGrinder
{
    public static void Grind(IReadOnlyEmployee emp)
    {
        //do stuff
    }

    public static void Main()
    {
        Employee rim = new Employee();
        rim.FirstName = "Rim";
        Grind(rim);
    }
}




This would guarantee the object is read-only at compile-time and it's easy to create the interface using the VS2005 refactor option extract interface. If you're going with design-by-contract, interfaces would be the way to go anyway I think and they would allow you some more finegrained control on which properties should and should not be read-only (or even available at all), instead of the catch-all const modifier.

Hope this does help [wink]
July 02, 2006 04:24 PM
jollyjeffers
I'll follow this up in summary as my next journal entry [wink]
July 02, 2006 06:59 PM
Muhammad Haggag
Quote:Original post by remigius
...

While this works in theory, it's a total pain to do that for every class you have. It simply doesn't scale, in terms of programmer time.
July 02, 2006 07:40 PM
Muhammad Haggag
Quote:Original post by Anonymous Poster
Const is generally regarded as bad practice in C# is it has several limitations, and can cause problems with multi-component systems when you recompile an individual library. This is because the compiler copies the value of a const field into the other libraries components that reference the const. If you change the value in your library and recompile/redistribute the changed library, the other files will continue to use the old value unless they are recompiled. Also consts can't be created at runtime which makes and type of object const problematic.

...

It looks like you're talking about const in the context of "Defining a compile-time constant", like PI. We were talking about const as a form of guarantee that an object you pass to a function isn't changed by the function. Two different things [smile]
July 03, 2006 06:37 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement