Ten C# Keywords That You Shouldn’t Be Using

Let me start off by saying that language design is hard, very very hard. Not only is the technical implementation of the language incredibly difficult, but creating a language that will satisfy any significant percentage of its users is an almost impossible task. With some languages you have considerations such as backward compatibility that will hold it back, and in others you simply have such disparate types of users that you are forced to incorporate some less-than-pure functionality into the language.

The C# language is an interesting beast born out of a C-style syntax, but with an aim on extreme type safety. Like most every language on the .NET platform, one of its main goals was to keep the developer from doing stupid things, or at least keep the developer from forgetting to do certain things. C# though falls into the category I mentioned above where the users of the language are extremely diverse, used in everything from military hardware to videogames to my blog. Because of that there are certain features that different types of developers are going to expect. Business users, for example, will expect speed of development. They want things to be simple, unbreakable, and just easy to develop in general. Videogame writers will want speed and control. Sure they don’t want things to be super hard to develop with, but ease of development isn’t their top priority.

Because of the fact that I come from the world of business software (and not game development), there are many features in C# that I think the average developer just shouldn’t be using unless they have a very good reason to do so. Some of these are very obvious, and others maybe not so much. All of which could get you in a bit of trouble if you use them incorrectly.

1) sealed – I went ahead and put what is probably the most controversial keyword in this list first. Sealed. There are two types of people in the C# world, those who love sealed and those who want to seal those other people in a tomb (how witty). I am in the latter camp. In terms of the .NET Framework, I can understand why Microsoft would want to make certain things sealed, but in most application it just makes absolutely no sense. If you start hearing people talking about performance improvements of sealed classes, and you’re not working on the space shuttle’s guidance system, then smack them. Smack them hard.

2) goto – Some of you may be looking at this and wondering if it is even in the C# language, and the answer to that is yes, yes it is. Some of you may be aware that a goto isn’t really as evil as Dijkstra’s paper might have led you to believe, it is the abuse of gotos that is really bad. In fact, we have many equivalent statements which do the same thing as a goto, only in a more structured manner which doesn’t allow abuse. These are “return” (when used in the middle of a method), “break”, and “continue”. Have you ever used one of these? Sure you have. Have you used a goto? Probably not, and if you do, you better have a good freakin’ reason. Especially if you are using it for something as silly as exiting from a nested loop.

for (int i = 0; i < 10; i++)
{
    for (int j = 0; j < 100; j++)
    {
        if (someStupidCheck)
            goto dufus;
    }
}

dufus:
    Console.WriteLine("I'm a dufus.");

3) unsafe – Well, if ever there was a keyword that told you not to use it…. Have you ever used unsafe? Probably not. And don’t start. The unsafe keyword is for people who are… well.. unsafe. You don’t want to be whispered about at the water cooler, do you? Basically unsafe means you are going to be using pointers, and we all know what happens when you start using pointers in managed code. And before you go off saying that you thought that all reference types used pointers, go read (and subscribe to) Eric Lippert’s blog. I would have put pointers in this list, but I specifically said “keywords”.

4) ref – You are probably thinking “Whaaaaat? What is wrong with ref? I use it all the time”. And if you are saying that, then well, you need to have your head examined. 9 times out of ten when I see ref being used it is because the developer who used it was too busy writing crappy code to wonder why they needed ref so often. Sure there are times when you need it, but as with almost anything, you better be able to explain to me exactly why you need it. And if you say that your reason is because you need to return five different scalar values from a single method, I am going to call shenanigans and make you write it again. And this time with your brain on.

public static void TooManyResultsYouIdiot(ref int me, ref int no, ref double design, ref byte software)

5) fixed – If you try to use this in your code, then it is likely that you need to be fixed. The fixed keyword is used for pinning. I’m not sure why they called the keyword fixed and the concept pinning, you would think that they would have just stuck with one. How about “pinned”? Too complicated? Right. Anyways, pinning is the process of fixing a value in memory so that the garbage collector won’t move it. You can’t really expect to have a pointer to something if the freakin GC is going to keep shifting it around, can you? But why would the GC keep moving things around? Well, because the GC compacts the heap occasionally. Don’t understand? Well, all you need to know is that it moves crap around and you can’t trust a variable to be in the same place twice. But you don’t have to deal with this unless you are using pointers, which as I already said, you probably shouldn’t be using.

6) stackalloc This is another one of those “unsafe” operations. You know, the ones I said earlier will force you to get checked out by a doctor. Some of you are probably looking at this and wondering what it is, and that is probably a good thing. But if you don’t know what the “stack” is, then that is a bad thing. If that person is you, then you need to do a bit of reading. stackalloc allows you to declare a block of memory on the stack instead of the heap, this allows you to avoid pinning the memory, since it won’t be affected by the garbage collector. Since nothing you are doing relies on this, stay away! If one day you are sitting there and you say to yourself “man I wish I could just allocate this buffer on the stack before I pass it to this method”, then and only then are you allowed to even look up what this keyword does.

7) unchecked – This is a keyword that you really really shouldn’t be using. First because it often doesn’t affect performance all that much, and secondly because it is so misunderstood that it probably doesn’t even do what you think it does. No, it does not turn off any sort of array bounds checking or anything of the like. No, it does not turn off all arithmetic overflow and underflow checking. It only works with integers. Yep, good old Int32. And you know what else, all integer math in C# is unchecked by default. Unless you turn it on via an option in the project, command line option, or using the “checked” keyword. So, the next time that someone wants to use “unchecked” because they need to speed up a loop, bet them a significant amount of money (or lunch) that it won’t do any good. Cause you’ll win.

8) struct – This is another one of those keywords that people are going to gasp and throw their hands into the air exclaiming that I have no idea what I am talking about. Well, I hate to break it to you, but you probably don’t know what you’re talking about. Many people use structs without understanding the very deep implications of using them. Just to name a few… they use ValueType.Equals instead of Object.Equals, if you pass a struct to a method then the struct is copied, but remember that reference types aren’t on the stack, so just their reference is copied. This can produce some odd behavior. Also, it is possible to box a struct and then have a modified version get passed around when you weren’t expecting it. The copy semantics of structs alone should make you pause if you are considering using one. There are a large number of pitfalls when dealing with structs, so unless you know why you are using it, don’t. Besides, heap allocations are so cheap now, right?

9) volatile – This is yet another keyword that falls squarely into the learn before you use it category. I say this because this is not a keyword to be avoided, but simply a keyword that should be used properly. If you have a field which is a reference type (or a few other specific types) and you know that you are going to be accessing it regularly from multiple threads, then you can mark it as volatile. Volatile basically tells the compiler and jitter to not allow certain optimizations which could cause trouble in multi-threaded code. As with anything though, it is never as simple as it looks.

10) implicit – This keyword made the list because it, in my opinion, can cause very subtle bugs. Not to mention the fact that there are very few legitimate uses for this in most software. The implicit keyword comes into play when implementing conversion operators and it signifies an implicit cast between two types. Now you may not be familiar with the terms “implicit” and “explicit” cast, well, implicit means that the cast just happens (like from short to int) and explicit means that you have to tell the compiler to do it (like when going from int to short). You can do some interesting things, like this:

class Program
{
    static void Main(string[] args)
    {
        Class1 variable = new Class2();
    }
}

internal class Class1
{
    public static implicit operator Class2(Class1 d)
    {
        return new Class2();
    }
}

internal class Class2
{
    public static implicit operator Class1(Class2 d)
    {
        return new Class1();
    }
}

Notice how we are assigning an instance of “Class2” into a variable of type “Class1”. And it compiles and works because an implicit cast is going on here. Sure there are very good uses for this, but there about 18 million more abuses for this. Most likely, if one type can be assigned to a variable of the other type, then it should inherit from it. This is not the case in reference types though, which for the most part, is why this behavior exists.

I’m sure that many of you will disagree with my list, and that is good. Please make sure you leave me a comment and let me know why you think the list is wrong, and what I should add or remove in it!

Be Sociable, Share!

64 comments

  1. Every tool has its job…

  2. I’d like to see the out keyword in your list too. if you’re going to return more than one result from a method. You might try to use an array (untyped) or a DTO instead. Much cleaner IMHO

  3. @Ivan Agreed, the out keyword and the ref keyword got a bit hand-in-hand.

  4. If you ship software, Sealed can be an important keyword. While as a dev it is nice to say you are on your own if you screw it up, support costs alone usually justify its’ existence.

    For internal LOB or one off applications, I agree with you.

  5. @Scott Agreed, there are certain situations where it is needed due to a class not wanting to be supported, needing to be changed in the future, etc… But for 90% of applications out there, people use it for silly reasons and just cause headaches for everyone else. And then there is also some software that uses it for a good reason, but then goes a little crazy with it.

    I for one would rather see an internal class than a sealed class, at least then you aren’t taunting me. :-)

  6. I think Ivan Porto Carrero is kinda right about the out keyword. I try to avoid it like the plague but even the plague strikes sometimes.

  7. Sealed is a good one when you start writing objects that are used to generate security contexts, authentication tokens, authorisation bits, etc. Those are all prime cases for sealed classes, even in internal/LOB libraries and applications.

    Oh and of course attributes. Attributes should be sealed obviously.

  8. i think all these keywords have their place.
    wouldn’t it be easier to guide their usage rather than suggesting they shouldn’t be used at all?

    fortunately, these keywords aren’t in java, so n00bs tend to avoid them anyway.

  9. Any construct, in the hands of the unenlightened, can be used poorly. The only keyword in the list above that would raise red flags and cause me to pull the fire alarm is GOTO. All other keywords can and should be used WHEN needed and with some understanding. I mean seriously, I have seen LINQ used poorly; I have seen OOP used poorly. Its all a matter of context and expertise.

  10. Funny how C# got much of it’s design ideas and language syntax from Java, and the 10 keywords you provide here don’t exist in Java (with the possible exception of fixed – if I understand your definition).

    Coincidence? :-)

    The fact that there’s a keyword called "unsafe" is just too funny.

    -ryan

  11. @vijay I never said that they shouldn’t be used at all (well, maybe the title said that a little :-) ), but in the post I outline that many of these keywords are easily misused, and therefore should be carefully considered. "10 Keywords in C# that you should carefully consider before using in your particular application" might not have made such a great title.

    @D.P. Agreed, if you know why and how to use them, then they should be used in moderation. The problem is that lots of smart people know how to use things, but still use them for pointless reasons.

    @ryan Yeah, I still chuckle when I see "unsafe" :-)

  12. I would say this a list o keywords that should be used carefully, not that you shouldn’t use them.
    On my OpenCV wrapper I use ‘unsafe’ and ‘fixed’ all over the place. That’s what they are intended for.
    If you are coding an web site. I would say, don’t use them. Ever…

  13. I’ve been bitten by using a struct instead of a class and not realizing the consequences in the past.

    As others have said, most of these aren’t "don’t use them" but "don’t use them unless you understand them".

  14. Apart from "ref", I cannot see any inexperienced programmers using these keywords. It is very likely that someone who is using these keywords in a wrong way was probably experimenting in good faith.

    Almost all of these keywords are useful in one context or the other. Even goto’s can be useful too for increasing performance (http://kerneltrap.org/node/553/2131)

  15. Obviously you’ve never had to write any .Net software that mainpulates huge amounts of in memory bitmap data. Then you’d very quickly find yourself thankful for that unsafe keyword.

  16. @Ivan you have to be kidding — returning an untyped array is better than using ‘out’?

    [i]Requiring[/i] casts is preferrable to keeping strongly typed data?

    I can understand not liking ‘out’, but if you must avoid it then use a typed value like a Tuple, KeyValuePair, or some other strongly-typed value. Preferring untyped data is just…bizarre.

    (Also, it should be noted that using ‘out’ can be faster than returning a custom data type, struct or reference, so this [i]may[/i] be an API design consideration. It can also promote more consistency with the existing framework, e.g. [i]int.TryParse[/i].)

  17. Well, as what Antao and Josh says, some of these keywords are useful in certain scenarios, especially during interop and manipulating memory data. Agreeably, a [b]normal[/b] developer should not need to use any of these keywords at all, unless he/she knows what they’re doing. I tend to avoid most of these keywords anyway.

  18. Another keyword to avoid is "new" in the case of overriding a non-virtual implementation

  19. It really depends on what you’re doing. If you’re writing an ASP.NET website you probably won’t need any of these keywords.

    But now imagine your code revolved around manipulating arrays containing millions of complex numbers. Imagine each of these complex numbers is stored as a separate object on the heap. Imagine each of them has to be allocated separately. Imagine the GC, keeping track of all of those millions of complex numbers you create each second. Imagine changing one of those complex numbers in one array and erroneously changing five other arrays at the same time.

    Now [i]that’s[/i] why I wouldn’t want to do something like that in Java. structs are great, as long as you know what they do and don’t confuse them with C++ structs.

  20. @Niki I would argue that most people doing these sorts of applications aren’t using C# very often anyways. But maybe I don’t have my ear to the ground in the "millions of complex numbers" application genre.

  21. Good list. I disagree with the out keyword in the comments. I think it can serve a very useful purpose when developing APIs and if you don’t want to force your users to consume an out variable, then provide an overload that doesn’t use it.

    bool Validate(target, out RuleViolationCollection violations);
    RuleViolationCollection Validate(target);

    Just my opinion though…

  22. @Paco – That is a [b]solid[/b] number 11!

  23. @Ryan Gray: yes the L from solid.

    Hmm I just checked this in mono (and I guess MS.Net will do the same):
    int i = int.MaxValue + int.MaxValue;

    I got the following warning:
    The operation overflows at compile time in checked mode(CS0220) http://msdn.microsoft.com/en-us/library/y169h3te(VS.71).aspx

    The compiler settings in ms.net and mono are different. So I disagree with unchecked not needed, because your code will compile different on a different compiler.

  24. @Justin: Well, the number-crunching/signal processing applications I’ve seen in the last 10 years often had the same problems that other applications have: Applications become bigger and bigger, which makes development harder. User want simpler user interfaces. Interfaces to different systems become a requirement. That’s the kinds of problems where Java and C# really shine in contrast to typical "number-crunching languages" like Fortran or C++.

    By the way: you’re probably aware that all the "oddities" you list for structs apply to ints or bools, too. Would you recommend we shouldn’t use those value types, and instead use reference-type wrappers? Then why should things like System.Drawing.Color or System.Drawing.Point be reference types? I find it much more natural that they behave like int’s or double’s.

  25. @Niki Point taken, I honestly am not in those fields, so I am not aware of their "tools of choice".

    And yes, the "oddities" of reference semantics for some reason don’t seem to odd to developers when they are dealing with primitives such as integers and booleans. But when you declare something that looks like a class, but then operates under totally different semantics, it can surprise some people. Again, I’m not advocating that we don’t use these features at all, I’m advocating that people educate themselves.

  26. @Justin How do you define "something that looks like a class, but then operates under totally different semantics"? Does "containing methods" fit that description?

    If so, then [i]int[/i] doesn’t fulfill the definition, as it has several methods — CompareTo(), Equals(), ToString(), etc.

    Or are you operating under the Java "exclusion" principal — "all types except those in [insert list here] are reference types."

  27. @Jonathan I’m referring to the definition of the struct themselves, I wasn’t very clear on that. Developers create them in a very similar manner, and then you can even use them in a very similar manner (why does the C# compiler let you use the "new" operator with them?)

    And I would say that even structs which have more than one value can be confusing as well. As an example, the Point struct that was mentioned earlier. I’m not saying that it isn’t a struct for very valid reasons, but I am saying that it can be confusing to developers. And most developers don’t understand the implications of substituting one for the other. They just hear that they are "faster".

  28. Why does the C# compiler let you use "new" with them? How else would you call the non-default constructor? A new struct-specific keyword?

    Other reasons for the simularity is that it makes the C# grammar simpler, making compiler design maintenance easier.

    As for developers hearing that something is faster and using it because of that…that should be a shootable offense. [i]Profile first![/i] (Unless you’re dealing with a specific problem domain, understand all the limitations, and require the features involved.)

  29. >> So I disagree with unchecked not needed, because your code will compile different on a different compiler. <<

    That.

    I got burnt answering a SO question where I converted example C code into C# and the questioner had "Check for arithmetic overflow/underflow" checked for whatever reason. If your code block requires unchecked surround it as such. Its all part of self-commenting code anyway.

  30. I’m not a fan of goto either, but it is necessary since switch/case statements require a break. Goto is the only way to get fall through. Just goes to show that every keyword is there for a reason, even if it has the chance of abuse.

  31. @James: switch should probably be on the list too =)

    @Justin: I gotta disagree with sealed. FxCop and framework design guidelines recommend sealing things you don’t intentionally mean to allow others to inherit. Ideally, you should plan out and know which of your classes you want public and inheritable, and therefore when to and not to use sealed. Sealing everything or leaving everything ‘all hanging out’ are both bad design, IMO.

    Many of the others you can’t avoid when it comes time to do any sort of COM interop. I recently had to write a managed wrapper around some C stuff, and had to use about all of these.

  32. I suggest to add switch to this list. Most of switch usings indicates poor OOP design. Almost every switch can be eliminated by using polymorphism, strategy pattern or lookup dictionary. Often switch violates DRY principle, often it introduces magic numbers. So if you goes to write switch, stop and think how it can be expressed without switch. I’m sure the alternative solution would be more elegant and more maintainable.

  33. You can use the state design pattern to get rid of switch statements as well. I’m a huge fan but it can be overkill for simple logic flow.

    I think it’s ok to use structs as long as you are sure to pass them with the ref keyword whenever you use them. :) Kidding…

  34. @Tony I only use structs in my programs and then just use ref everywhere!

  35. Nice article, I can agree with a lot of it. I just think you missed the most important one of all. The most often abused…

    ————-> [b]if[/b] <————-

    I know it sounds silly, but have really looked hard at method with several if statements? Often they can be removed or refactored out. Take a closer look next time you see more than one or two if statements in a function. Bottom line is simplify.

    My complete rant on the subject is at:
    http://csharptest.net/?p=198

  36. @Andrey: I agree that switch is often used by people without OO skills to simulate polymorphism, which is bad. But forbidding the switch statement wouldn’t do any good, they’d just use if/else instead, making the code even messier. You’ll can’t teach good OO design be forbidding keywords.

    And switches are really useful sometimes: for example pretty much any language parser has in its heart a
    switch (GetNextToken()) { case Token1: … }
    statement. Of course you could write an alternative "OO-style" solution, where tokens are classes, and instead of switches you have virtual methods, but that would violate DRY [i]big time[/i], and lead to a maintainance nightmare.

  37. I feel that this might have been better as a series of posts. There certainly are good and bad use cases for each of these keywords and the concepts they represent (with the probable exception of goto). That any of them should not be used, however, is obvious only to someone who already understands them on a fairly deep level, someone who is probably already qualified to use them anyway.

    Moreover, writing a few sentences about the effects of each keyword and asserting that they are clearly almost never necessary is not helpful, even if you are right. In particular, it does not encourage actually learning the correct usage of any of these things. Encouraging people not to do things they might screw up is not quite as good as showing them how to do better. For example, it’s all very well to say unsafe code is scary and confusing and won’t give you the performance benefit you might think it would, right up until you need to use unsafe code to interface with native-code libraries in some capacity. Now you either need to learn how to write unsafe code, or use some other language. "Well, you shouldn’t be doing that" isn’t always an excuse.

    You undoubtedly have opinions on how these keywords should be used, but "language design is hard, very very hard," and there is more than one side to each of these arguments. Show us you understand in more detail.

  38. Interesting that you use existing from nested loops as a bad use of goto. In my book, it is the only acceptable use of goto. C# lacks break to labels and break to labels are a good thing, so one must use gotos instead.

  39. @David My point is that if you are using gotos to jump out of nested loops, then there is a chance that you might need to refactor the code. There is probably a better way to write it. But I agree, that in certain situations (as was nicely described in Code Complete) using gotos to jump out of nested loops can look nicer than the alternative.

  40. Interesting list.

    I’m sure it will surprise readers here, but many times in my career, I’ve heard a developer say something like this: reference type arguments are passed by ref by default; thus the ref keyword is only meaningful with structs, i.e., value types. Frightening, I know.

    So, while I sometimes use [i]ref[/i] and [i]struct[/i], I understand your point about avoiding their use unless you really truly understand the implications. And in my experience most people do not understand them, or at least do not think them through well enough.

    I have mixed feelings about [i]sealed[/i]. I tend to leave classes open, but I also respect the argument that if you publicly expose an inheritable type, you’re implying that inheritance has been considered and members are marked protected and virtual appropriately.

    I’m curious what people think of Jeffrey Richter’s proposal to add a keyword that is between sealed and open; [i]closed[/i] is the term he uses I think. The point of the keyword is tell developers that they *can* inherit from the class, but the class was not designed with inheritance in mind.

  41. Interesting list, but I’m afraid I violate most of it. Between interfacing with unmanaged code and maintaining a stable API for external use, many of these keywords are invaluable. They also tend to generate extra review chatter, so it works out in the end. There is nothing like an unfamiliar keyword to focus attention on a block of code.

  42. The product I work on has millions of lines of C++ that aren’t going away any time soon. When incorporating new managed components (accessible via COM or C++/CLI bridges) we [b]must[/b] use the fixed keyword. No getting around it.

  43. thanks this is good to know especially for the newbie like me ..lolz

  44. I’m not going to talk about how I think this post to be worthless, just highlighting _one_ aspect of those keywords, and additionally mixing in personal attitude, but just let me comment on the sealed keyword:

    Actually, there was a discussion among the designers of C# if every class should be sealed by default, and that would’ve been a very, very good idea – it’s just this concept alienates what most people indoctrinated by half-hearted teachings of OOP.

    But, just for a minute, indulge me please, and honestly think about how many of the classes you encounter in your daily work are actually MEANT to be inherited. Designed from the ground up to be used as a base class. Because that’s what a class designer has to do, otherwise, inheritance is completely meaningless and leads only to code rot. 99.9% of all classes that are around are NOT designed to be inherted, and inherting from them does more harm than it is useful.

    This is highly suspect to people who were told during their education that inheritance is one of the most fundamental building stones of OOP, and well, it is. But it has to be applied correctly.

    Designing a class so that it makes a good base class is hard. Really hard, for all but the trivial cases. And judging how hard it already is for most people to provide a good interface design for their classes, you cannot really expect them to anticipate further uses of their classes when it comes to inheritance. This is why the majority of classes are so poorly appropriate as a base class. Which is why sealing any class by default is a good thing.

  45. @Jim Yep, I’ve heard all of your arguments before. Unfortunately I don’t agree with you. I don’t want you to bind my hands solely because you think I shouldn’t be able to change your class. Especially if you’re not going to give me the source.

    And yes, I agree that to design a class for proper inheritance is hard. But I don’t think that should trump giving me the ability to make a choice.

    What you are advocating for is stripping me of all choice and flexibility unless the creator of the class *chooses* to give me that control. Ick, sounds very ivory towerish to me.

    And as a final point, if you go look at almost any dynamic language they give you virtually complete control to change anything. And yet the sky does not fall. Because people quickly learn that while you can do anything, doesn’t mean you should, but having the choice makes your life a lot easier.

  46. Good list… But like people already have written its not that black and white. Its true… You SHOULD not use OUT if not necessary. Returning more that one result is not in the meaning of SRP. Or probably seperation of concerns is missed. If more than one result is used by context, its a more clean style to use an own return object with the needed properties or a typed enumerable as return value.

  47. I have to agree with you, but I was looking for reasons not too as I read your article. I’ve been programming for a long time. Started with Pascal, then VB, the VC, then PHP, Java, and now C#

    I used many of those like STRUCT but that was before I was using OOP and Classes. I guess VB lingers in the soul somewhere. :)

  48. Hi

    I think your blanket rejection of many of these features is unjustified Justin.

    A struct allows you to embed a member directly into the storage layout of a datum, for example declaring a class with only value type members means that all of the objects data is packed into a contiguous memory block.

    This makes marshaling that object’s data much easier (in terms of processing) than if each member had been a reference type (in which case each member would be (in reality) a pointer to the data – i.e. an object graph).

    By preventing people from creating their own structs you make it much harder to do this – granted the run-time layout is an implementation issue but that does not mean we can dispense with it does it?

    For example DateTime and Decimal are structs, and declaring members of these types means the data that comprises them is part of the types physical storage, contiguously laid out.

    By allowing users to create their own (blittable) structs allow aggregate data structures to exist that are contiguous and can be passed to native code using ‘ref’ or ‘out’ which then passes a (true) pointer into the native code, this is very fast.

    If you need to allow managed code/native code to do a lot of common access to such data then passing refs is very fast indeed.

    We have ‘message’ structs here that are pure value types with rather a lot of fields and these can be manipulated as contiguous blocks and accesses rapidly for IO over TCP with no marshaling or serialization this is very fast.

    So this justifies ‘struct’ and ‘ref’.

    Now as for pointers, sure these should not be used unless there is no reasonable alternative, but you can ONLY use them to point to value types, so if you ever did need to use them, then once again value types (structs) are essential.

    Pointers (unlike ‘ref’) can be stored, that is a pointer is is a type and is stored inline as a field when used in a struct. You can’t get a ‘ref’ to a struct and store that, you can only use ‘ref’ when passing to/from methods (you can use TypedReference but lets not get into that).

    So pointers allow you to create linked data structures in memory that can be shared/accessed by native and managed code, this cannot be done using reference types.

    I can build a large complex tree of structs (that use pointers to point to nodes) in managed memory and then simply pass a ref to the root of that tree into a native method. Providing the structs in the nodes are all blittable, then the native code can do stuff with that data without any marshaling or serialization overheads.

    Personally I think there is a fundamental design weakness in .Net’s design regarding how types are defined and instances of them declared, but that’s another story!

    Hugh

  49. So am I the only one that uses ref more for documentation than for passing structs around? If I am writing or working on an API I know other developers will be working on I’ll use”ref” as kind of a warning that the object they are passing is about to be altered. I don’t usually make a habit of writing my public methods to alter the objects they are being passed, but it does come up sometimes.

  50. Matt Whitfield

    I guess I’m late to the party. But I think sealed has it’s uses. If you want to seal individual methods, that can be very useful. So I’d like to propose that ‘sealed’ is removed from the list and you add ‘new’ (aka ‘screw over polymorphism’) instead

Leave a comment