Freigeben über


Use your legs, not your back

In C# you can "lift", "raise" and "hoist", and they all mean different things.

To "lift" an operator is to take an operator that operates on non-nullable value types, and create from it a similar operator that operates on nullable value types. (We are a little bit inconsistent in exactly how we use the word "lifted", which I documented here.)

For example, if you have

public static Complex operator +(Complex x, Complex y) { ... }

 then we automatically generate a lifted operator for you that basically does this:

public static Complex? operator +(Complex? x, Complex? y)
{
return (x == null || y == null) ?
(Complex?) null :
(Complex?) (x.Value + y.Value);
}

"Raising" by contrast refers to events -- not to exceptions, which are of course "thrown". Another common term for raising an event is "firing". Given that it makes sense to standardize on one or the other, the usage committee people felt that between "raising" and "firing", they'd pick the less bellicose-sounding one. Which is maybe a bit silly, but if you've got to pick one, then I suppose that's as good a criterion as any.

Finally, "hoisting" is what we call it when the compiler emits a field for what looks like a local variable, because that local variable is in fact a captured outer variable of an anonymous function (or a local of an iterator block). When you have:

class C
{
void M()
{
int x = 123;
Func<int, int> f = y=>x+y;
...

then we rewrite that as if you'd written something like:

class C
{
private class Locals
{
public int x;
public int Method(int y) { return this.x + y }
}
void M()
{
Locals locals = new Locals();
locals.x = 123;
Func<int, int> f = locals.Method;
...

 see, local "x" has been "hoisted" up and out of its declaration space.

Even after a number of years on the compiler team, I still misuse "raise", "lift" and "hoist" in casual conversation; that they have such similar meanings in English and dissimilar meanings as jargon is unfortunate, but usually doesn't result in too much confusion.

Comments

  • Anonymous
    June 18, 2009
    In choosing between "raising" and "firing" an event, it seems to me that "less bellicose sounding" is a far less useful criteria than "doesn't collide with existing common usage". Since "raising an exception" is common terminology in other contexts, whereas nobody "fires" anything in other contexts that I can think of (well, except for events), surely "fire" would have been a much better choice. "Triggered" or "activated" might also have been reasonable alternatives. Sometimes when writing a spec, you need a good thesaurus to hand...

  • Anonymous
    June 18, 2009
    Oh, if you only knew the woes of translating "raising the event" (or "firing" one, for that matter) to Russian! Or, say, the difference between "statement" and "operator"... It's actually something worth keeping in mind - no matter how clear you can get it for English speakers, other languages will still have its own problems that you can't really anticipate in advance.

  • Anonymous
    June 18, 2009
    @pminaev - you could just do what the Germans do: mangle your language and shove in English words everywhere!  Then you end up with lovely expressions like "das Exception throwen" (instead of: die Ausnahme ausloesen) and "das Event raisen" (instead of: das Ereignis ausloesen).  It sounds as horrid to the ear as it looks to the eye, but I suppose it's better than when people use the wrong word and end up saying things like "throw the event" which just makes you go "huh?"  It also doesn't help that whoever translated the C# reference into German wasn't at all bothered by turning "throw" and "raise" into the same word (ausloesen).

  • Anonymous
    June 18, 2009
    The comment has been removed

  • Anonymous
    June 18, 2009
    I once accidentally installed the Dutch .NET version on my development PC. It was terrible. The C# compiler errors were all given Dutch. Even terms like "overloaded” (as in overloaded methods) were translated to Dutch. But not a single Dutch programmer uses a Dutch translation of "overloaded" (translated to "overbelast" in .NET) and while I'm Dutch, it was like reading German :-)

  • Anonymous
    June 18, 2009
    In vb6 speak, one raises events. So that's a bit old school. But in the entire web, we talk about firing events. Also Google thinks "fire events" (96.8 M hits)  is bigger than "raise events" (50.4 M hits). Although substantial, I wonder for how long you can keep it up ;-)

  • Anonymous
    June 18, 2009
    can anybody say me the meaning for the qoute below the title "Use your legs, not your back"  

  • Anonymous
    June 18, 2009
    @askitanna - it's good advice when lifting a heavy object. (I guess a heavy object would be one with a finalizer?)

  • Anonymous
    June 19, 2009
    @askitanna - Whenever you lift (or hoist or raise) something heavy, you should take a stance that allows you to use the strength of your legs, not your back, for safety purposes.  In the US, it is very common to simply say "Use your legs, not your back" to describe the entire safe method of getting something heavy up off the ground.

  • Anonymous
    June 19, 2009
    The funniest story I ever heard about the machine translations was the name Osama Bin Laden coming out as "Osama the Loaded Rubbish Container" (as an explanation, think the Recycle BIN on your Windows desktop, and the word "laden", adjective, is self-explanatory)

  • Anonymous
    June 27, 2009
    Hi, Eric You said that hoising captures local variables (hope I'm not putting words in your mouth), but I did some research of my own and found out that it is not true. I wrote some code along these lines to look into the matter: .... var toBeHoisted = 1;
    Func<int, int> f = a => a + toBeHoisted;
    var before = f(1);
    toBeHoisted = 2;
    var after = f(1); .... I would assume that since that variable got "hoisted", a snapshot of it was made in function "f" (it was captured in your words) and variables "after" and "before" should have coincided, but they did not ! Then I wrote this code: .... var toBeHoisted = 1;
    Func<int, int> f = a => {toBeHoisted += 1; return a + toBeHoisted;};
    f(1); .... Again I was in for a surprise, I had thought that variable "toBeHoisted" would not be changed from the anonymous delegate, but it was ! [[ The variable itself is captured, not the value of the variable. When you make a change to the variable in one place, everyone that captured that variable sees the change. Now is it clear why what you're seeing is expected. -- Eric ]]