Open GoogleCodeExporter opened 9 years ago
Workaround: create a local variable and initialize it with CodeGen.InitObj(),
e.g.
if (T.IsValueType) {
@object = g.Local(T);
g.InitObj(@object);
} else {
@object = g.Local(Exp.New(T));
}
Original comment by qwertie...@gmail.com
on 16 Aug 2010 at 11:04
[deleted comment]
Hi,
It's more or less exactly as you say - there is no 'default' constructor for
value types, because initializing them this way would be inefficient. You are
also right regarding the 'workaround', except I don't think it's a workaround,
but rather that it's the way to do it correctly.
The reason for this is probably the fact, that while it is meaningful to
initialize a value type in a separate space on the stack and then copy it into
the storage variable (the newobj case) - to avoid partially initialized value
types, there is no such point in creating a zero-filled area on the stack and
then copying this to the variable, which is why initobj operates on the storage
area directly.
If you look at the code generated by the C# compiler, it works pretty much like
this, except that under some circumstances it even avoids the newobj in favor
of a call of the constructor directly on the storage variable (a third option
for value type initialization).
In short - there is no way to create a zero-initialized value type on stack,
except by providing a temporary local variable and throwing initobj at it. I'm
also not really convinced that it's usefull to have Exp.New emulate this
behavior the way C# does, but if you have a valid use case, please let me know
and maybe I'll change my mind :) After all, this all comes down to the lack of
documentation (Issue 1).
Best Regards,
Stefan
Original comment by StefanSi...@gmail.com
on 17 Aug 2010 at 6:55
Well, it seemed to me that Run#'s API was trying hard to look like C#, with
"Public.Static.Class", For/ForEach loops and so on. An this is nice, it means I
can do metaprogramming without knowing CIL intimately. C# (and VB too?) nicely
harmonizes structs and classes so that you can always use "new T(...)" whether
T is a struct or class; I think having this feature in Run# would be a good
thing. In any case, I agree, documentation would help.
By the way, this is unrelated but I have repeatedly made the mistake of writing
code like
obj.Invoke("Func", args);
instead of
g.Invoke(obj, "Func", args);
The first form is required only for a subexpression, and the second only for a
standalone statement. Unfortunately, the first form compiles fine but doesn't
work.
It makes the API a bit confusing that two forms are required. I would prefer to
use only the first form and then pass it to g to execute, e.g.
g.Do(obj.Invoke("Func", args));
But I don't see a method in g for doing this. Did I miss something?
Original comment by qwertie...@gmail.com
on 17 Aug 2010 at 2:39
Hi,
The only problem with the New() is that C# avoids creating a temporary local
variable and copying it's contents, which is not all that easy to do with
RunSharp - though it quite likely doesn't affect performance in any meaningful
way (after all, there are worse things in the generated code than that ;)
As for the Invoke, this is a very interesting idea and I'll definitely look
into it.
Regards,
Stefan
Original comment by StefanSi...@gmail.com
on 17 Aug 2010 at 3:13
Even if New() has to create a temporary local variable, I think that would be
better than throwing an exception.
Original comment by qwertie...@gmail.com
on 18 Aug 2010 at 8:34
Sure, will fix it.
Original comment by StefanSi...@gmail.com
on 20 Aug 2010 at 8:52
Original issue reported on code.google.com by
qwertie...@gmail.com
on 16 Aug 2010 at 10:45