views:

1566

answers:

21

In light of this question I thought it'd be really neat to have a similar question about C#/.Net.

So, what is the most awkward or misleading method name of the .Net and/or C# API?

+25  A: 

System.DateTime.Add(*)

I think all the DateTime methods starting with Add are misleading, considering DateTime is an immutable struct and cannot be changed (these methods return values reflecting the addition).

So:

DateTime.Add
DateTime.AddTicks
DateTime.AddMilliseconds

etc.

I would've gone with:

DateTime.Plus
DateTime.PlusTicks
DateTime.PlusMilliseconds

etc.

Arguably the same is true of certain string methods, such as string.Replace; but I don't really know what else you would call that.


Some have raised the objection that since the behavior of the addition operator (+) for numerical values is intuitive (and does not modify the value of the instance), the DateTime.Add(*) methods are no less intuitive. Here's my response to that.

Let's phrase this objection as:

You don't expect that i + 5 modifies i, so why would you think d.Add(t) is any different?

Now let's repeat this exact same question, but with English words in place of code:

You don't expect that i plus 5 modifies i, so why would you think d add t is any different?

See what I'm saying?


Wow, if you want to see one of the longest comment threads ever on an SO question (that I've seen, anyway), just get a load of the comments to this answer. Apparently the notion that the word Add suggests mutability is far more subjective than I thought.

Dan Tao
The operator Addition on integers doesn't change the immutable object when adding another integer I guess you dont Think that's Strange so what is in your oppinion the difference?
Rune FS
+1. I've been bitten by this oh so many times
Isak Savo
@Rune FS: The difference is that programmers are used to working with operators, and in fact `DateTime` does accept the `+` operator in conjunction with `TimeSpan` values, which is intuitive. But this operator is pronounced "plus", not "add". What if the `Int32` struct had an `Add` method? What would you expect to happen from calling `i.Add(5)`? That's significantly less intuitive. Furthermore, there is precedent for methods with names starting in `Add` to mutate mutable objects; e.g. `ICollection<T>.Add`.
Dan Tao
`ICollection<T>.Add` doesn't return a value. `DateTime.Add` returns a `DateTime`. I think the method signature is enough of a disambiguator between mutable and immutable versions of `Add`. If the Add method returns a value of the same type as the object, then the original object was probably not modified. If the Add method returns no value, then it better have mutated some state somewhere, or what's the point of the method? I see no need to change the name of the method in addition to its signature.
Joel Mueller
@Joel, doesn't `StringBuilder.Append` have a return of `StringBuilder` (which is in this case just itself) and mutate itself?! I think you're being shortsighted about the ambiguity here.
jball
@Joel: First of all, I'm not trying to start some great big argument over these methods. It's just awkward, really. That said, I disagree that the return value alone disambiguates the behavior of the method. (The *documentation* does, but not the return value.) Consider `StringBuilder.Append` -- modifies the `StringBuilder`, returns itself. This is so you can do `mutabletext.Append("More").Append("Text");` A developer unfamiliar with the behavior of the `DateTime` methods might expect, e.g., to be able to do `myDate.AddMonths(1).AddDays(14.0)` to increase `myDate` by a month and two weeks.
Dan Tao
@jball: Looks like you and I both had the same thought ;)
Dan Tao
I don't think Plus is any different to Add, but I agree it is confusing.
SLC
@Dan - I don't think this is a great big argument - I just don't think it's all that awkward. What would be awkward is if immutable types couldn't use methods called "Add" even when it's the sensible choice. My point is that if an `Add` method returns a value, and you use the returned value instead of the original variable, it doesn't matter if the actual object is immutable or not. I think this rule of thumb applies to `StringBuilder` and fluent interfaces just as much as it does to `DateTime`. You don't lose any functionality by treating StringBuilder as if it's immutable.
Joel Mueller
To put it more succinctly: If you use the return values of methods that return values, you rarely have to worry about whether or not the object is immutable. The only reason for someone to get in trouble with `DateTime.Add` is if they ignore the fact that the method returns a `DateTime`.
Joel Mueller
@Joel: All good points. I guess it basically just comes down to consistency (which is pretty tough to nail down 100% when you're working on a library *by yourself*, let alone on a gigantic API like .NET, I will concede). The fact is that `StringBuilder.Append` returns the underlying `StringBuilder` instance for convenience. There's no reason a developer should be *expected* to write something like `stringBuilder = stringBuilder.Append("more text")` just because `Append` returns a value. My point is pretty modest: the word `Add`, in the naming of these `DateTime` methods, is (to me) misleading.
Dan Tao
@Joel: Anyway, I think the fact that we're even having this discussion makes it abundantly clear just how subjective language can be. Apparently what is counterintuitive to me might be the most logical thing in the world to someone else. Clearly, though, while plenty of developers have no problem whatsoever with the naming of these methods, there are still plenty of *others* who *have* found it confusing... well, at the time of me writing this message, at least fourteen others ;)
Dan Tao
@Dao tao I guess I din't express my self clearly why do you in the first place think that a Date is mutable? do you think it makes sense to say If I add one day to Jan 1st 2010 then jan Jan 1st 2010 equals Jan 2nd 2010? If not then the date is clearly not mutable and trying to mutate a value that really isn't mutable would be misleading (Remember DateTime are valuetyped so 2010/1/1 is a _value_ just like 5 is a _value_)
Rune FS
@Rune FS: Personally, I think you've carried your argument a little too far. (1) I don't "think that a Date is mutable"; I just think the `Add` method is counterintuitively named because it *sounds* like something that a mutable type would have. (2) Value types in .NET are not inherently immutable. Consider `Point`, which has (strangely enough) an `Offset` method that changes the instance. (3) You've given a name to a value and conflated the two. If I have an `int` variable whose name is `five`, it might seem ridiculous to write `five = 6;` but I can still *do* it.
Dan Tao
@Rune FS: Basically, it all comes back to the name: `Add`. To me, this sounds like something that changes an instance. For this reason I maintain these methods are confusingly named. Suppose `Int32` had a method `ChangeTo(int newValue)` that changed nothing and just returned `newValue`; would you argue that this method were *not* misleading, just because it should be obvious that an `Int32` is immutable? What I'm saying is, whether or not it's obvious that a `DateTime` is immutable is beside the point; it's *the naming of the method* that is, in my opinion, confusing.
Dan Tao
I can't say that I ever really thought twice about this. `DateTime` is a value type; it really doesn't matter what its methods are called, none of them could possibly be mutators. This isn't any more awkward or misleading than `String.Insert`. Methods that actually **do** mutate the underlying struct, like `Point.Offset`, are a **lot** more awkward.
Aaronaught
@Aaronaught - there are actually people out there who don't *already understand* the differences between value types and reference types. `DateTime.Add` makes it harder for them to learn those differences because it makes a value type look like a reference type, due to the common English usage of the word 'Add'. When I **add** an ounce to a glass of beer, I've changed the original glass.
Jeff Sternal
@Jeff, this is simply isn't true. As Rune FS explained earlier, you can *add* 2 to 1 and you get 3, but that doesn't change the meaning of 2 or 1. This might confuse raw beginners to programming but that doesn't make it a misleading API. Addition is a pure mathematical function; no reasonably-experienced programmer could possibly believe that it's actually a mutator. If somebody out there doesn't understand the difference between a value type and a reference type then the whole point is moot (and that person should not be let near a compiler).
Aaronaught
@Aaronaught: `string` is a **reference** type that is *immutable*. `Point` is a **value** type that is *mutable*. From these two examples, how is it so obvious that `DateTime` is immutable simply by virtue of being a value type?
Dan Tao
@Dan: That's exactly why I said that structures like `Point` and `Rectangle` are the awkward/misleading ones. Value types aren't supposed to be mutable - combining copy-on-assignment semantics with mutation semantics makes no sense and can lead to all sorts of subtle errors. Would you expect to be able to change the `Value` property of a `Nullable<T>`?
Aaronaught
@Aaronaught: No, I agree with you; I'm just saying: immutability is not something you can just **know** about a type without, you know, checking the documentation (or figuring it out the hard way). Yes, it's generally accepted that having a mutable value type would be a bad design. But you seem to be saying that any smart person would just automatically assume that a value type is immutable simply because that makes sense, *regardless of method names*.
Dan Tao
@Aaronaught: Consider the question I posed to Rune FS: if there were an `Int32.ChangeTo` method, would you not consider this a poorly named method, simply because any smart person would *know* that `ChangeTo` couldn't possibly change the underlying `Int32`... even though, to a **lot** of developers, that's what the name of the method would imply?
Dan Tao
@Dao must admid I find it funny that you use a different name (changeto) to argue that Add is a bad name. Ask you self the same question but stick with the original name (ie int32.Add) does that change your answer?
Rune FS
Dan - You seem to be implying that a given method name can only be used for one type of operation across all the classes that exist. `Add` must mutate the object, and if it doesn't, it should have a different name. Suppose there are three types that all have a method called `Save`. One type writes to a database when Save is called, one saves a file to disk, and one uploads some data to a web service in the cloud. Should I invent new words to avoid giving different methods on different types the same name, or just use the method name that makes the most sense *for that operation on that type*?
Joel Mueller
@Dan: An `Int32.ChangeTo` method wouldn't even make sense for that type. There is, however, a `Convert.ChangeType` method, which unsurprisingly leaves the original object alone. Consider if C# had date literals like VB and you could write `#5/14/2010#.AddDays(1)`. What would you expect this to do? I maintain that if people get this wrong, it's *their* fault, not the Framework's fault for having a "confusing" method name. If I say "take your date of birth and add 1 month", that doesn't imply that you should (or could) physically change the date on which you were born.
Aaronaught
@Rune FS: You are missing my point. **You** have said that the behavior of a method should be obvious given a type's (allegedly) obvious immutability -- i.e., that its behavior should be clear from its *type* rather than its *name*. **I** am saying that this argument carried to its logical conclusion would imply that a method might be called something completely nonsensical and still have obvious behavior, which is (to me) clearly untrue.
Dan Tao
@Joel: I think you're arguing with a straw man. I never said the `Add` method was somehow *wrong* for being called what it is -- simply that it is confusing (to many developers). Besides that, there is a different word (`Plus`) that, **in my opinion**, more directly conveys the behavior exhibited by `Add`. It isn't like I'm arguing for a designated term for every conceivable behavior a method might exhibit; again, *all I am saying is that the word `Add` can be confusing*.
Dan Tao
@Aaronaught: I think we must be misunderstanding each other. You said: "An `Int32.ChangeTo` method wouldn't even make sense for that type." **That is exactly my point.** The word `ChangeTo` would suggest that the underlying object gets changed, which couldn't be true, **so its name would be misleading**, am I wrong? I think it's pretty clear that at least *some* developers think that the word "Add" implies changing the underlying object; but since that is not possible for a `DateTime` -- because `DateTime` values are immutable -- the `Add` method, to these developers, has a misleading name.
Dan Tao
@Dan - That is perfectly fine, and you are entitled to your opinion. In my opinion, method names should be verbs, or have verbs in them, and that makes `Plus` a poor name. I can't think of any method names that better-describe what's going on than `Add` and I don't think the existing name is *confusing enough* to justify choosing a non-verb or non-descriptive method name.
Joel Mueller
"I am saying that this argument carried to its logical conclusion would imply that a method might be called something completely nonsensical and still have obvious behavior, which is (to me) clearly untrue." I respectfully disagree. You can infer something about even methods that don't have a name at all. What does `Func<DateTime, DateTime>` do? Well, it takes a date and returns a date, so it's probably not mutating the date or it would be `Action<DateTime>`. We still don't know exactly what the function is doing, but we can make a reasonable guess as to the proper way to use it.
Joel Mueller
@Joel Mueller: I hear what you're saying; all I would like to point out is that there's a difference between *not having a name* and *having a misleading name*. You're right that from a method's signature alone I might be able to produce a rough deductive guess as to its behavior, or what its behavior might be *like*. But in my opinion, name trumps signature when it comes to providing clues about the method's behavior. And anyway, method **names** are the topic around which this question has been framed. Besides, even granting your point, there's still that pesky `StringBuilder` example...
Dan Tao
@Joel Mueller: Another point just came to mind (on the subject of methods having verbs as names): I don't think .NET is 100% on your side with this one. Consider the static constructors for `TimeSpan`: `FromDays`, `FromHours`, etc. Not verbs. Or the LINQ extension methods `Where`, `Any`, `OfType`, `AsEnumerable`... again, not verbs. Or `List<T>.AsReadOnly`. Are these all bad names? Should `List<T>.AsReadOnly` be called `List<T>.ConvertToReadOnly`? Wouldn't that be more confusing?
Dan Tao
...and if we guessed from the signature of `StringBuilder.Append` that the object was immutable, would our code break? No. If we ignore the signature of `DateTime.Add` does our code break? Yes. All I'm saying is that the name of a method is only one part of its signature, and ignoring the other parts is a bad idea. Also, I don't agree that `Add` is a misleading name; it describes the operation very well. It's unfortunate that English uses the same word to describe mathematical addition and appending to a collection - maybe `ICollection.Add` is the misleading name. Why not `ICollection.Append`?
Joel Mueller
@Dan - your examples of methods without verbs are all good examples of exceptions to a general rule that have good justifications. They're all conversion functions or specifically designed to imitate SQL grammar. The existence of exceptions does not invalidate the rule. You might make the argument that there's a good justification for `Plus` being an exception, but so far I remain unconvinced.
Joel Mueller
@Joel Mueller: Think of a number, any number. Now add 5 to that number. Now add 3. Is the number in your head now 8 greater than the original number, or did you simply perform the calculations I asked and mentally discard the results? If the latter is true, then I have to conclude that we really **do** just have different intuitions about whether `Add` implies mutability or not. But in this case, I must *also* conclude that you have performed this mental exercise very differently from the way I think most people would.
Dan Tao
No Dan, there is a *new number* in my head that is 8 greater than the original number, which I can still remember, because I didn't replace it with the new value.
Joel Mueller
@Dan: I'm sorry, but if some developers think that `Add` implies changing the underlying value, without even noticing that the method returns a *new* value or understanding that the type is immutable, then they shouldn't be developers. "Add 5 hours to the time on your watch" does not mean "set your watch ahead 5 hours." Nor does "add two and three" mean "change the number two into a different number." Your `ChangeTo` example (analogy?) is a red herring, as far as I can tell.
Aaronaught
But Joel, I didn't say: "Now remember the result of adding 5 to that number"; I just said, "Add 5." You thought up the new number on your own. I think this is what most people think of when given this task: `n = n + 5;` But verbally the sentence "Now add 5" more closely resembles `n.Add(5);` This is really just `n + 5;` (if that were even a legal statement), which would essentially be saying, as I said: "Perform the calculation and discard the result." So my point is that I think the average person would *hear* the statement "Add 5" and think of it as `n = n + 5;`
Dan Tao
OK, guys, let's just accept that we are the [North- and South-going Zax](http://www.youtube.com/watch?v=sfI9e4BX0lU).
Dan Tao
@Aaronaught, in idiomatic English, you are always implicitly adding **to** something. Think of the way that many children learn how to add: they start with a pile of two gumballs and move three more gumballs into their pile, *modifying their pile* (their variable). It's true that doing so doesn't change the (platonic) number two, but who's arguing that? `DateTime.Add` is misleading because it implies that a date time variable is a pile of gumballs rather than an immutable value. (Who says "add 5 hours to the time on your watch"?)
Jeff Sternal
If people really added numbers the way you expect `DateTime.Add` to work, they would be *incapable* of remembering the number they started with, because they would have overwritten that part of their memory with the new value.
Joel Mueller
@Joel - because people only have one variable slot? D:
Jeff Sternal
If this were Ruby, you'd have .Add and .Add!, where the latter is a mutator and the former is, well, a function. It's a great convention. As someone who learned to code on functional languages, I always have the **opposite** confusion: I assume there's no side effect until told otherwise, even if the object in question is a reference type.
Isaac Cambron
@Jeff - because the original value was destroyed when it was mutated into the new value. We're talking here about how `DateTime.Add` is confusing because it doesn't update the value it's called on. If DateTime were mutable and Add modified it, how exactly would you expect the computer to remember the original value after an Add operation, short of storing a copy somewhere else prior to performing the addition?
Joel Mueller
I wouldn't expect the computer to remember the original value - unless I stored it in a variable.
Jeff Sternal
@Jeff - exactly my point. Because I can remember the original value when adding numbers in my head, without doing anything special to store it in a different "variable" then I must not be mutating the value in my head - or I'd be unable to remember the original value, just like your computer.
Joel Mueller
Must ... get ... last ... word. But seriously, I think we're getting into deep water here: I certainly don't have a comprehensive theory of cognition, so I'll have to second Dan about the Zaxes.
Jeff Sternal
I should have known: we're not the first bunch that's had this conversation about DateTime.Add (http://stackoverflow.com/questions/241134/what-is-the-worst-gotcha-in-c-or-net). It seems this question is very close to being a duplicate.
Jeff Sternal
@Jeff, really, kindergarten analogies? Programmers understand - *must* understand addition as an abstract mathematical concept, not as moving around gumballs. `2 + 2 = 4` - there are 3 terms in that equation, computing the sum did not change either of the operands.
Aaronaught
@Aaronaught - no one is saying that developers shouldn't have to understand this: but the question concerns what's misleading in the .NET framework. Given that the .NET framework contains both mutable and immutable value types, this is ambiguous at best.
Jeff Sternal
@Aaronaught: You keep saying over and over that values are immutable. But we're talking about *variables*. That `DateTime` is an immutable struct does not mean that when I type `DateTime d = Date.Now;`, suddenly `d` is **The Moment of 6:46 PM EST on Friday May 14 2010** for all eternity. For that to be the case, `d` would have to be declared `const` -- as a *constant*, **not** a *variable*. The former, which is a *value*, cannot be changed. Nobody's arguing against that. But `d` is just a variable, that *stores* a value. It *can* be changed -- to a *different* value -- by assignment. (Cont.)
Dan Tao
@Aaronaught: The reason that so many programmers get tricked by `DateTime.Add` is that they interpret a line like `d.AddDays(1.0)` to be equivalent to `d = d + TimeSpan.FromDays(1.0)`. You can go on all you want about this being stupid, because `DateTime` is immutable and to expect otherwise is to misunderstand a fundamental concept of programming, but I just think you're combining concepts that are actually different. The fact is: a **value**, in the platonic sense (to borrow a term that Jeff used), cannot be changed; a **variable** can -- and is, all the time.
Dan Tao
@Aaronaught: Anyway, I get what you're saying, and yes, it would be nice if all developers understood that a method call on an immutable struct is not going to change its value. But it would also be nice if methods on immutable objects didn't have names that threw lots of developers for a loop. And you know what, here's yet another example that just occurred to me: consider the `++` operator. `i++;` increments `i`. Yes, it's an operator, not a method call; but it's *remarkably* similar in appearance to `d.AddDays(1.0);` Do you think `i++` makes intuitive sense but `d.AddDays(1.0)` does not?
Dan Tao
@Dan: No, we're not talking about variables, we're talking about values. Variables have to be *assigned* to. Method calls can't change the contents of a variable. Assigning a value to a `DateTime` is no different from assigning a value to an `int`. It doesn't have to be declared `const` - that's absurd, you can just as easily assign a different value to a `DateTime` variable, as you yourself have pointed out, but that's not *mutation*, that's *assignment.* If there really are "so many" programmers making this mistake, then that's frankly horrifying.
Aaronaught
The difference between a variable and its contents is one of the first things you're supposed to learn about programming, I mean it's literally lesson 1 in programming 101. If there's somebody out there who can't grok the difference between a `DateTime` variable, which can be assigned any value, and a `DateTime` value, which refers to a specific point in time just as `int` refers to a specific integer, then please, please, if you're one of those people and you're reading this, start searching for another career.
Aaronaught
Aaronaught, calm the fuck down bro
Pierreten
+20  A: 

One answer: IList<T>.IsReadOnly vs IList.IsReadOnly. The meaning is not clear at all, and it turns out these two properties have different meanings. :)

The blog post I created is summarized here:

There are two types of updates:

  1. An update that changes the value of an element already in the collection, and does not change the number of elements in the collection. e.g., the index setter.
  2. An update that changes the number of values in the collection, but does not change any of the values of the elements in the collection. e.g., Add(), Clear(), etc.

For IList

The value of IsReadOnly is false if either type of update is allowed. It is only set to true if both types of updates are not allowed.

but for IList<T>

[IsReadOnly] should be true if either type of update is not allowed. It is only set to false if both types of updates are allowed.

Stephen Cleary
That's bizarre!
Dan Tao
What are the two meanings? Educate us, please.
Rubys
I blogged full details here: [http://nitoprograms.blogspot.com/2009/11/icollection-isreadonly-and-arrays.html](http://nitoprograms.blogspot.com/2009/11/icollection-isreadonly-and-arrays.html)
Stephen Cleary
Yeah I've run into this one before, and it's a real PITA.
Greg Beech
+12  A: 

Here's a classic: Path.GetInvalidPathChars, which "is not guaranteed to contain the complete set of characters that are invalid"

Stephen Cleary
True. But thinking about it, it's probably unavoidable. A) it may vary per filesystem so you'd have to also tell it where you want to save and b) it's mostly use as a first check on user input so checking those unprintable makes little sense.
Isak Savo
True. But why have a useless method, then? I'd much prefer having a method that did get the invalid path characters for a given filesystem.
Stephen Cleary
+7  A: 

Another one that has tripped up many innocent coders: Socket.Connected, which is next to useless. It "reflects the state of the connection as of the most recent operation. If you need to determine the current state of the connection [complex code horror removed]".

Stephen Cleary
I'd actually like to see said removed code horror. =P
Erik Forbes
I'd love to learn about the complex horror code, too! I've just been experimenting with sockets earlier this afternoon and have run into exactly this problem -- namely that `Socket.Connected` cannot be relied upon.
stakx
The quote is from the MSDN documentation; follow the link to see it, if you must.I really do not agree with their recommendation. A socket cannot really *know* if it's connected - the best design is to [assume it's connected until a write fails](http://nitoprograms.blogspot.com/2009/06/using-socket-as-connected-socket.html).
Stephen Cleary
@Stephen: Considering that the, "check if a socket is connected" technique Microsoft advocates there is, "try to write to it, see if it fails," I have to agree with your design advice, since it is morally equivalent but less stupid. Also, the connection might die in between checking the connectivity and trying to write.
Brian
This isn't an API issue - it's just how TCP/IP works.
John Saunders
@John - the API issue is that the Connected property exists at all.
Joel Mueller
AFAIK, TCP/IP has a ping-like packet that it sends back and forth to verify that the connection is still alive even if no data is being written. I think these packets are sent something like every 20 minutes of inactivity, so they're not exactly going to give up-to-the-second info.
rmeador
@rmeador: there is no such packet in TCP/IP. Some protocols built on top of TCP/IP might implement such a packet.
John Saunders
+1 for this, it's infuriating
SLC
re TCP/IP ping - there is such a packet but needs to be explicitly enabled and the default timeout is on the order of hours. Pre-Win2K, this timeout could only be changed on a systemwide basis (now it is possible to change it on a per-connection basis). Other problems include the fact that this keepalive packet may be legally dropped by intermediate routers and many embedded TCP/IP stacks don't recognize it. This is why [I recommend](http://nitoprograms.blogspot.com/2009/05/detection-of-half-open-dropped.html) implementing it in the application protocol if necessary.
Stephen Cleary
+16  A: 

It's not a method, but protected internal has claimed many victims.

Many people (cough cough) initially expect it to mean that only derived types in the current assembly can access the member, but it actually permits derived types in any assembly and any type in the current assembly to access the member.

Eric Lippert explains why this is eminently reasonable in his blog post here (thank you Brian for the link!). It's just a shame it's ambiguous.

Jeff Sternal
That's annoying. Any others that use "OR"?
Nelson
Indeed it has. They should've just made it `protected or internal`.
Dan Tao
Awkward and misleading, probably. But it makes sense. And I think `protected or internal` is much worse syntax. Eric Lippert's explanation: http://blogs.msdn.com/ericlippert/archive/2010/03/25/knights-knaves-protected-and-internal.aspx .
Brian
@Brian, many thanks for the link, which I'd completely forgotten about - I'm going to edit it into my answer so casual observers don't think the C# team made an arbitrary call there.
Jeff Sternal
It depends on the context. There's the MSDN way: *"member can be accessed by any code in the same assembly, or by any derived class in another assembly."* Okay, that's true, but now read that sentence with "AND"; it makes *more* sense and is still completely accurate! But if you think about it in the other context: *"only code which is in the same assembly AND descends from this class can access this member"*, then "AND" is wrong - and the people who're confused are probably thinking about it in that context. Ironically, MSDN uses the right context but the wrong word. MSDN should say "AND".
Charles
+3  A: 

Not quite a method name, but I think the behavior of the ValidationExpression property in a RegularExpressionValidator is misleading. A regular expression normally does a partial match unless you explicitly use the start/end anchors (^ and $). The validator always does a full match, with or without the anchors. If you want a "partial" match, you actually have to explicitly match any characters. So you have the following "conversion":

  1. matchthis -> [.]*matchthis[.]*
  2. ^matchthis -> matchthis[.]*
  3. matchthis$ -> [.]*matchthis
  4. ^matchthis$ -> matchthis
Nelson
Unfortunately just one more case where regular expressions aren't very regular. Seriously if anyone can find two completely different products with exactly the same regex system I would be shocked.
Jeff Mc
Even Visual Studio uses a different regex system than the languages you write using Visual Studio.
Joel Mueller
+11  A: 

System.Linq.Enumerable.Reverse

The Reverse extension method is strangely named, in my opinion. Why? Because List<T>.Reverse already exists, and it reverses the ordering of the list itself. The Reverse extension method, on the other hand, just enumerates over any IEnumerable<T> backwards.

I would've called it Backwards, maybe (or even Reversed, with a "d"). That wouldn't have implied performing any alteration on the list. Plus that way if I wanted to enumerate over a List<T> backwards I could call:

myList.Backwards()

instead of:

((IEnumerable<T>)myList).Reverse()

or:

myList.AsEnumerable().Reverse()
Dan Tao
But... that's the whole point of LINQ. Functional programming, which entails no side-effects whenever possible.
Rubys
@Rubys: Yeah, I know; it's just strange when there's already a method with that *exact same name* in existence, and it does something totally different. Notice they called the method that enumerates over a collection in a sorted order `OrderBy` as opposed to `Sort`. (Wouldn't that have been confusing?)
Dan Tao
The method to reverse a list (that behaves in the same way) is called reverse in haskell too, and lisp. Don't blame microsoft !
Ed Woodcock
Nice find Mr. WoodCock
Pierreten
+1  A: 

I'm fond of CompilerParameters.GenerateInMemory (System.CodeDom.Compiler), which doesn't, at least with the C# CodeProvider

alexdej
If I'm not mistaken it creates a temp file which gets deleted automatically? You don't have to worry about managing it, but it's still not "in memory"
Nelson
+1  A: 

Another "oldie but a goodie": ICollection.IsSynchronized; its documentation defines a "thread-safe collection" as one that is not thread-safe during enumeration.

Stephen Cleary
+8  A: 

System.Enum.ToString

This might seem like a weird answer, but the first time I learned that ToString on an enum actually returns that enum's name, I was pretty shocked.

To me, this was as surprising as if the following code:

const int SomeSpecialConstant = 1318942;

Console.WriteLine(SomeSpecialConstant.ToString());

Had produced this output:

SomeSpecialConstant

!

In the end, Enum.ToString is extremely convenient, but I still find myself scratching my head about it from time to time.

Dan Tao
Um... No it doesn't. Perhaps you intended to define it as an enum, which would then make sense considering the rest of the post?
Rubys
@Rubys: I'm saying, when I first found out about `Enum.ToString`, I found it as surprising *as if* the code I posted produced that output. I know it doesn't -- which is what I would expect! Know what I'm saying?
Dan Tao
I actually did not know this. But this is extremely useful!
Earlz
@Earlz: I won't lie; it makes me uneasy!
Dan Tao
@Dan Tao : I see. Might be a good idea to rephrase that a bit, to avoid misinterpretation by people like me ^^
Rubys
@Dan: So what's the problem with this? Is it the fact that the actual enum names are compiled also, instead of only their base types (e.g. int)?
Nelson
@Nelson: I didn't say it was a problem. It's just totally different from what I originally expected (i.e., for `Enum.ToString` to do basically the same thing as `int.ToString`). Maybe it's logical to you. In any case, since it was a method whose behavior surprised me, I felt it made sense as an answer to this question.
Dan Tao
@Dan: It's semi-logical to me. :) I understand your point, though.
Nelson
What you're actually saying is it returns the name *instead of the value* as a string. Took me a while to figure that out!
Ed Woodcock
@Ed Woodcock: Exactly. Prior to learning this about `Enum.ToString`, I thought of enums as, essentially, `const int` values that were logically grouped together. In some ways, they are; in others (such as this), they are a very different animal.
Dan Tao
+4  A: 

ASP.NET developers should recognize this one:

HttpResponse.IsClientConnected

This method only works when running the web app in IIS, not in the development web server.

Marnix van Valen
+1 good tip, might come in handy one day
Neil N
+3  A: 

I find it odd that a generic List has the ForEach extension method and generic IEnumerable does not. Especially since IEnumerable exists to support the foreach() statement.

  var myList = new List<SomeClass>();
  myList.ForEach(x => Console.Write(x.SomeProp)); // works

  IEnumerable<SomeClass> myEnumerable = myList;
  myEnumerable.ForEach(); <--- What? Where is it? Invalid
Matthew Sposato
Eric Lippert wrote about this: http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx
Sarah Vessels
Eric explains why it wasn't supported, but then the [Rx team](http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx) decided to support it, calling it `Do` and `Run` instead of `ForEach`. While I agree with Eric that it's not purely "functional," I also agree with the Rx team that it's very useful (and find it ironic that the functional guys are the ones who added it :).
Stephen Cleary
It's pretty easy to add as an extension method though, if you really want it
Ed Woodcock
The F# guys added it too, calling it `Seq.iter` - and they're more functional than just about anyone at Redmond.
Joel Mueller
...and the PFX guys named it `ParallelEnumerable.ForAll`. Argh!
Kha
+7  A: 

Just saw this nugget

Not every Freezable object can be frozen. To avoid throwing an InvalidOperationException, check the value of the Freezable object's CanFreeze property to determine whether it can be frozen before attempting to freeze it.

from MSDN

Christopherous 5000
Why would you.. That's like saying "Not every object that implements IDisposable can be disposed. Check CanDispose property first". That is completely moronic.
Earlz
Seems reasonable to me. Whether an object is freezable or not may be something that needs to be determined at runtime.
Brian
@Brian: It seems reasonable, but the point of implementing an IFreezable interface is so that, you know, you can *actually freeze the object*. You're thinking of an IMaybeFreezable, or something like that.
RCIX
I've encountered plenty of interfaces in the framework which had similar methods for various reasons. In this case, I could easily imagine an object which can be in a mutable state and thus cannot be frozen, particularly in the case that the object has asynchronous functions.
Brian
+2  A: 

I found people coming from C++ backgrounds have really tough time visualising that structs instances created using new dont go on the heap!!

The mechanism is hidden deep in CLR - When new is used with reference types it is converted to "newobj" CIL instruction and for value types it is converted to "initobj"

Edit: This makes a perfect interview trick question

MSIL
C# structs **are not** anything like C++ structs.
Earlz
Funny, I thought this was an implementation detail.
Brian
A: 

Microsoft.VisualBasic.Strings.Trim() doesn't always return the same value as "string".Trim()

The VB method will only remove actual space characters(from hitting the space key), while the other function will remove all the other white space characters(carriage returns, etc) with it.

rossisdead
I imagine that's why it's in the VisualBasic namespace, where methods that are backwards-compatible with VB6 go to die...
Joel Mueller
Joel: Haha, probably. But it sure tripped me up since I had no idea they worked differently.
rossisdead
+7  A: 

My vote goes to the ICloneable interface and its Clone method.

The term is so vague and ambiguous that important people at Microsoft actually tell you not to implement it or use it in public APIs.

Not only does it tell you nothing about what a "clone" is (is it a memberwise clone? Deep copy? How deep? What if it has external references? What if it references a singleton?) but it's entirely possible for this method to return a different type from the original, since the return type is just System.Object.

It's a thoroughly pointless interface that provides no discoverability whatsoever, and yet it's there, ever present, leading another programmer astray every week. Look at the ICloneable questions and see for yourself. Endless confusion.

Aaronaught
+3  A: 

I find the 'TryParse' methods to be awkward, and somewhat misleading.

int i = 15;
var b = int.TryParse("what", out i);
// now i is 0 and b is false

Maybe this is just a minor complaint, and I understand the decisions that went into that API, but it's not entirely clear that i becomes 0, and having to use an 'out' parameter can be a real pain, especially if you don't care what the resultant value is (only that it is valid).

mgroves
When you pass something as an `out` parameter, initializing it is futile. Also, a method that receives an `out` parameter *must* give it a value, and since int can't be null, 0 is the obvious choice. It sounds like you want a version where `i` is a `ref` parameter instead. Then TryParse() could simply leave it alone when the result is false.
Charles
A method that takes an `out` parameter **has** to initialize it. It can't assume the parameter is initialized, so it can't use its value. But I agree that a `ref` parameter would be better here, since it allows you to specify a "default value"
Thomas Levesque
+3  A: 

Select()

When MS created LINQ, they used the nomenclature of SQL. So Select, Where, OrderBy, etc. The problem is that these functions already exist in other languages, but with different names:

  1. LINQ uses Select where everyone else uses Map
  2. LINQ uses Where where everyone else uses Select

This is really confusing.

Isaac Cambron
+1  A: 

Just discovered yet another answer. If you take two types FromType and ToType, with a conversion from FromType to ToType, then foreach has an interesting behavior:

foreach (ToType entry in collection)

works beautifully when collection has a known element type (e.g., List<FromType>). However, it fails with an InvalidCastException if collection doesn't know its element type (e.g., IEnumerable).

This little gem is courtesy of Bill Wagner; see Item 3 in Effective C#. The behavior is a holdover from the pre-generics .NET days...

Full repro code:

using System;
using System.Collections;
using System.Collections.Generic;

class Program
{
    public sealed class FromType
    {
    }

    public sealed class ToType
    {
        public static explicit operator ToType(FromType from)
        {
            return new ToType();
        }
    }

    static void Main(string[] args)
    {
        var test1 = new List<FromType>() { new FromType() };

        try
        {
            foreach (ToType entry in test1)
            {
                Console.WriteLine("Cast OK.");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }

        IEnumerable test2 = test1;
        try
        {
            foreach (ToType entry in test2)
            {
                Console.WriteLine("Cast OK.");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }

        Console.ReadKey();
    }
}
Stephen Cleary
+2  A: 
    public Form1()
    {
        InitializeComponent();

        Control.ControlCollection controls1 = this.Controls;

        controls1.Add(new Button());
        controls1.Add(new Button());

        ControlCollection controls2 = new ControlCollection(new Form());

        controls2.Add(new Button());
        controls2.Add(new Button());

        ControlCollection controls3 = new ControlCollection(new Form());

        foreach (Control item in controls1)
        {
            controls3.Add(item);
        }

        foreach (Control item in controls2)
        {
            controls3.Add(item);
        }

   }

After execution:

controls1.Count = 1

controls2.Count = 2

controls3.Count = 3

Now replace:

Control.ControlCollection controls1 = this.Controls;

with:

ControlCollection controls1 = new ControlCollection(this);

After execution:

controls1.Count = 2

controls2.Count = 2

controls3.Count = 4

Lesson?

System.Windows.Forms.Form.ControlCollection != 
System.Windows.Forms.Control.ControlCollection
Enriquev
+1  A: 

String.IsNullOrEmpty(" ") returns false. Once could argue or easily believe it should return true.

Something like String.IsNullOrEmptyOrWhitespaceOnly(string) would be nifty, if the name could be shorter.

Matthew Sposato
I would seem my wish has been fulfilled. I just discovered that .NET 4 includes the new static method string.IsNullOrWhiteSpace() which returns true for null, empty or whitespace only strings. Whitespace is defined as characters that return true when passed to char.IsWhiteSpace(). http://msdn.microsoft.com/en-us/library/system.string.isnullorwhitespace.aspx
Matthew Sposato