WARNING: This is an HTML post, for the sake of readability, if your client can see HTML posts, do it, it doesn't contain any script or virus :-)
I can reformat a non-HTML post if you want me to (and if this doesn't see correctly with non-HTML viewers)
Ok, I'm fed up with this so I'll explain the situation here and my approach (which sucks), and see if anyone can give a better solution to this.
I'm making a way to have several parameters of a class (a instance of a class) accesed via strings (for a script system)... I don't want to use the default property collections in C# because: 1) that'd give me access to all public properties/member variables, and that's not what I want, and 2) that'd not be easy to manage from other languages.
So that doesn't count as an option.
My current approach is:
- I have an interface IScriptable, where I define some methods that all classes with accesable as scripting components will have (basically, a function that will set the parameters and associated values)
- I have a base class, CScriptableObject (which implements IScriptable) with the basic implementation of this class, with no parameters. Rests of the classes will derive from this, and override certain methods.
- Let me make an example of a CScripttableObject derived class:
/*
Color Chart (for those of you with an HTML-viewer for usenet:
Blue: normal 'blue' stuff in Visual Studio.Net
Green: Comments
Purple: Variables that will be accessed from the Scripting Engine
Red: Name of the variables in the script (example, in a script, var1 will access variable1)
Black: Rest of the code
*/
public class MyScriptableClass : CScriptableObject
{
public MyType variable1, variable2;
private OtherType someMoreVariables;
// This is overriden from the CScriptableObject's one
public override void InitializeMembers()
{
base.InitializeMembers(); // We'll call the parent class first, just in case
// initialization of variables
someMoreVariables = new OtherType();
variable1 = new MyType();
variable2 = new MyType();
}
// This is overriden from the CScriptableObject's one
public override void SetObjectInfo()
{
ScriptObject = new ScriptObjectInfo
( "MyTypeClass", // String name for this class type [for the scripting engine]
new ScriptParameter("var1", ref variable1), // We set a parameter, named "var1", referencing variable1
new ScriptParameter("var2", ref variable2) // We set a parameter, named "var2", referencing variable2
);
}
// [etc...]
}
Ok, so now we have that we have a class "MyType", with 2 script-accesible variables, "variable1" and "variable2". The script-name for the class type will be "MyTypeClass", and the variable names (for the script) are "var1" and "var2". There are other variables in the class (someMoreVariables) which are not accesible through the script (as they are not defined for the script in the ScriptObjectInfo).
Now in the base CScriptableObjects I have some methos to retrieve parameters.
Ok, I had this implemented in C++, using pointers and stuff, and there was not a single problem with it. Now I've come to this problem in C#
I can use a reference to reference-types, or "boxed" value-types, and store it in an "object" class. HOWEVER:
- If I ever assign (within the class) a value to the value-type, the reference is referencing a copy, thus doesn't get updated:
Example:
CORRECT
-------
int i = 5;
object o = (object)i;
o = 10;
Console.Write("{0},{1}",i,(int)o);
Result: 10, 10
INCORRECT
---------
int i = 5;
object o = (object)i;
i = 10;
Console.Write("{0},{1}",i,(int)o);
Result: 10, 5
I can understand why this happens though, when I do "i = 10", the compiler is internally doing "i = new System.Int32(10)", so the reference gets lost, as it's allocating new memory.
Now there are only two workarounds for this:
1) Make a wrapper class for value types.
This leads me to two problems:
- You can't overload operator =, and the only way to do it is setting an implicit operator, for example:
public static implicit operator CIntParameter(int val)
{
return new CIntParameter(val);
}
- That'd allow me to do:
CIntParameter i = 10;
However, that creates a new object anyway, so the reference would get lost anyway. Thus, the only way to do it is using a Get() and Set() parameters so that it returns or sets the int value within my CIntParameter.
That is, for one, a pain in the ass to program with (not being able to use "="), and for two, error-prone, because I could be misusing the = operator at some point (with another CIntParameter) and it would assign the reference of the other, so the original parameter reference would get lost.
2) Go unsafe and use pointers for everything... but I'd be using Unamanged C++ if I was to do that, right?
So, any of you know of any different approach to this problem, or can think of a better solution? (or been there?)
In conclusion, all of these Value-Types and Reference-Types deriving from the same System.Object is stupid IMHO, but the fact that you can't overload operator =, or you can't just assign a reference which the system could be tracing for value-types (it's tracing it with the garbage collector whenever you change a reference, so that it knows if the object is referenced by any other thing, and if it's not, dispose it, it could be easy for the CLR to reassign a reference, maybe using another different keyword). Or you could just have CLR-optimized reference-types for basic values (ref int, ref double, or something like that).
I hope I'm not being wrong with all of this, if I am, please someone explain it to me, and tell me how to handle this case. Hope I've explained myself clear.
Thank you very much for the long reading, and sorry for the HTML, those of you who can't see it. I can reformat a non-HTML post if you want me to (and if this doesn't see correctly with non-HTML viewers)
Javier Campos
Virtual Media Systems, S.L. 5 1479
[Continues...]
As for 1) of the approaches (wrapping up the value-types in my own class)
there are even more problems.
I can't directly use any operators other than comparison on the
CIntParameter (or however you want to call the class), because, unlike in
C++ (where you can overload non-static operators), all operator overloading
in C# must be static, so I have to make a "new" for each of them.
Example:
C++ Non Static Operator
-----------------------
/*
This allows you to do:
CVector a(1,1,1);
CVector b(2,2,2);
CVector *pv = &a;
a = a - b;
At no point in the "a = a - b", memory is allocated, as you can work
directly on the member variables of the instance [because the operator is
not static]. At the end of the operation, pv still points at the same
location "a", and it's members (pv->x, pv->y and pv->z) point to the correct
result of the operation "a = a - b", thus, all pv->x, pv->y and pv->z
value's will be -1, which is correct.)
*/
CVector &CVector::operator -= (CVector &v)
{
x-=v.x;
y-=v.y;
z-=v.z;
return *this;
}
--------------------------------------------------------------
Best C# Approach to an operator '-' overloading for Substracting two Vectors
--------------------------------------------------------------
/*
Now I can do this:
CVector a = new CVector(1,1,1);
CVector b = new CVector(2,2,2);
CVector pv = a; // It's referenced, as CVector is a reference-type class
a = a - b;
At the end of "a = a - b", 'a' is a newly created vector, which doesn't
have the same memory address as the older 'a' we created, thus, 'pv' now
still points to a vector (for which we have no variable other than 'pv')
containing (1,1,1), whereas 'a' now contains (-1,-1,-1).
For what I've learnt of C# (I'm still a newbie though), there is no way I
could make such an operation, and keep 'pv' pointing to 'a' after using any
operator.
*/
public static CVector operator - (CVector v, CVector v2)
{
return new CVector(v.x-v2.x, v.y-v2.y, v.z-v2.z);
}
Just one more inconvenience of method 1 that I wanted to share with you (and
see if anyone has a different approach)
Thank you for reading,
Javier Campos
Virtual Media Systems, S.L.
> public static CVector operator - (CVector v, CVector v2) { return new CVector(v.x-v2.x, v.y-v2.y, v.z-v2.z); }
What's wrong with:
public static CVector operator - (CVector v, CVector v2) {
v.x = v.x - v2.x;
v.y = v.y - v2.y;
v.z = v.z - v2.z;
return v;
}
This is the same as your C++ implementation. I don't think the minus
operator should modify any of it's operands, though. This is a terible
design.
-JG
> INCORRECT --------- Line 1: int i = 5; Line 2: object o = (object)i; Line 3: i = 10; Line 4: Console.Write("{0},{1}",i,(int)o);
Result: 10, 5
I can understand why this happens though, when I do "i = 10", the compiler
is internally doing "i = new System.Int32(10)", so the reference gets lost,
as it's allocating new memory.
Nope, you got it all wrong. In line 2, the compiler intenally allocated
memory for the boxed integer and copied it's value there. Like this:
Stack Heap
+-------+ +------+
i | 5 | | ... |
+-------+ +------+
o | ref --+--------> | 5 | // this is the boxed integer
+-------+ +------+
And yes, you're right, the ony way to reference to a value type is through
(unsafe) pointers.
Hope that helps,
-JG
"Juan Gabriel Del Cid" <jd*****@atrevido.nospam.net> escribió en el mensaje
news:eo**************@tk2msftngp13.phx.gbl... public static CVector operator - (CVector v, CVector v2) { return new CVector(v.x-v2.x, v.y-v2.y, v.z-v2.z); }
What's wrong with:
public static CVector operator - (CVector v, CVector v2) { v.x = v.x - v2.x; v.y = v.y - v2.y; v.z = v.z - v2.z;
return v; }
Yeah, that happens to me for being so quick when writing, I'm sorry, you are
right.
This is the same as your C++ implementation. I don't think the minus operator should modify any of it's operands, though. This is a terible design.
-JG
Yes, actually, my problem with this (I made up the CVector thing) happened
when trying to make the wrapper, and I started using explicit operators, so
I countinued doing so till I realized it was completely wrong (as I had to
use new to create new instances)
I'm sorry for my mistake, my bad... I got too excited talking about the
problem :-)
Thank you,
Javier Campos
Virtual Media Systems, S.L.
"Juan Gabriel Del Cid" <jd*****@atrevido.nospam.net> escribió en el mensaje
news:uY**************@TK2MSFTNGP10.phx.gbl... Nope, you got it all wrong. In line 2, the compiler intenally allocated memory for the boxed integer and copied it's value there. Like this:
Stack Heap +-------+ +------+ i | 5 | | ... | +-------+ +------+ o | ref --+--------> | 5 | // this is the boxed integer +-------+ +------+
That makes more sense, still doesn't help my problem at all :/ And yes, you're right, the ony way to reference to a value type is through (unsafe) pointers.
Yes, this is one of the problems I'm facing with this. Having to use
pointers for all the possible scripted classes kinda makes me want to just
wrap the existing C++ engine, instead of porting it. Makes no sense at all
to port it once you have to use unsafe/unmanaged code.
I guess having a way to track "pointers" would not be that hard to make;
taking the garbage collector is running and actually checking for
references, it shouldn't make such a different in performance anyway, but I
might be all wrong with this (if I am, someone correct me).
They made a reference-type for a valued-type also (strings)... not that it
works the same, but if they can make an exception in the runtime (so it
optimizes better), I'm pretty sure it wouldn't be that hard to implement
some more, for other value-types like int, double, or whatnot... and I would
like to see those included in future releases. Having to wrap it is already
bad, but not having it in the standard framework (taking the same system is
limiting you to do some pretty basic stuff -like this-) is even worse, in my
oppinion.
I think I'll just take the wrapping approach and see how it goes for some
time... if I find that's too much of a pain in the ass, I'll just do that
part in C++ and keep doing the rest of the thing in C#. Still, I'd love to
hear oppinions from you all about this, and what did you do, if you ever got
into a situation like mine.
Thank you for pointing out my mistakes, Juan :-)
Javier Campos
Virtual Media Systems, S.L. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Rafael Veronezi |
last post by:
Just to fix, correct me if I am wrong...
With reference types (objects), if I assign an object to another, the
assignment will be the address of the object, and not a copy of it's
contents right?...
|
by: daniel |
last post by:
This is a pretty basic-level question, but I'd really like to know, so
thanks for any help or pointers you can provide (like what I would
google for ;o)
Suppose:
<code>
myFunc()
{
|
by: ALI-R |
last post by:
Hi All,
First of all I think this is gonna be one of those threads :-) since I have
bunch of questions which make this very controversial:-0)
Ok,Let's see:
I was reading an article that When...
|
by: Zach |
last post by:
When it is being said that, "value types are created on the stack or inline as part of an
object". If a value type is created in an object, and that object is being
called, the value type in that...
|
by: Ben R. |
last post by:
I'm curious about the differeng behavior of the "new" keyword when dealing
with value versus object types. If I'm correct, when I do:
dim x as integer
There's no need for "new" to be called...
|
by: Jon Slaughter |
last post by:
I'm reading a book on C# and it says there are 4 ways of passing types:
1. Pass value type by value
2. Pass value type by reference
3. Pass reference by value
4. Pass reference by reference.
...
|
by: garyusenet |
last post by:
I have 'cli via c# on order', and in the mean time am reading 'Pro C#
2005 and the .NET platform' (Andrew Troelson). I'm just reading about
the 'five types defined in the CTS'. Specifically Struct....
|
by: Zytan |
last post by:
This returns the following error:
"Cannot modify the return value of
'System.Collections.Generic.List<MyStruct>.this' because it is
not a variable"
and I have no idea why! Do lists return copies...
|
by: Robert Dailey |
last post by:
Hi,
I noticed in Python all function parameters seem to be passed by
reference. This means that when I modify the value of a variable of a
function, the value of the variable externally from the...
|
by: Naresh1 |
last post by:
What is WebLogic Admin Training?
WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge required to effectively administer and manage Oracle...
|
by: Oralloy |
last post by:
Hello Folks,
I am trying to hook up a CPU which I designed using SystemC to I/O pins on an FPGA.
My problem (spelled failure) is with the synthesis of my design into a bitstream, not the C++...
|
by: Carina712 |
last post by:
Setting background colors for Excel documents can help to improve the visual appeal of the document and make it easier to read and understand. Background colors can be used to highlight important...
|
by: BLUEPANDA |
last post by:
At BluePanda Dev, we're passionate about building high-quality software and sharing our knowledge with the community. That's why we've created a SaaS starter kit that's not only easy to use but also...
|
by: Rahul1995seven |
last post by:
Introduction:
In the realm of programming languages, Python has emerged as a powerhouse. With its simplicity, versatility, and robustness, Python has gained popularity among beginners and experts...
|
by: Ricardo de Mila |
last post by:
Dear people, good afternoon...
I have a form in msAccess with lots of controls and a specific routine must be triggered if the mouse_down event happens in any control.
Than I need to discover what...
|
by: ezappsrUS |
last post by:
Hi,
I wonder if someone knows where I am going wrong below. I have a continuous form and two labels where only one would be visible depending on the checkbox being checked or not. Below is the...
|
by: DizelArs |
last post by:
Hi all)
Faced with a problem, element.click() event doesn't work in Safari browser.
Tried various tricks like emulating touch event through a function:
let clickEvent = new Event('click', {...
|
by: F22F35 |
last post by:
I am a newbie to Access (most programming for that matter). I need help in creating an Access database that keeps the history of each user in a database. For example, a user might have lesson 1 sent...
| |