473,406 Members | 2,633 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

ValueType object

Hi,
Im a bit confused about when you cast a value type to an object.
I have a property grid wich stores the data and the defualt as
objects.

the data is limited to primitive types, structs and strings.
the structs only have primitive types.

however once ive set the data to the defualt,
if the data is a struct then any edits change the defualt data as well
wich was unexpected !

however it doesnt happen for primitive types.

I thought value types were always passed by value,
does this mean an object is actually able to behave
as a pointer to a struct ?

I gues il have to identify if its a struct and copy it with reflection ?...
but why is there not even Type.IsStruct ?
would this be the same as !IsClass&&!IsInterface&&!IsPrimitive ?

Colin =^.^=
Jun 27 '08 #1
7 1672
I have a property grid wich stores the data and the defualt as
objects.
Well, you haven't really explained this setup... and unfortunately the
devil is probably in the detail here... can you add more info?
however once ive set the data to the defualt,
if the data is a struct then any edits change the defualt data as well
wich was unexpected !
I'm guessing that your structs are "mutable" - i.e. you can edit them
once created. This is almost always a big mistake; where "almost" means
"it would take a long discussion to explain some borderline scenarios
where it might just possibly make sense to have a mutable struct". In
general, structs should be /immutable/ - i.e. once created they never
change, but can be replaced (hence the need to provide CreateInstance
etc on a TypeConverter).
I thought value types were always passed by value,
does this mean an object is actually able to behave
as a pointer to a struct ?
Yes; the term is "box"; when you box a value-type to an object, an
object is created on the managed heap that encapsulates the value-type -
*broadly* as though you had a class with a single field member (although
it isn't really that).

If you then give two different bits of code the same boxed copy, then
they will be stomping all over each others values
I gues il have to identify if its a struct and copy it with reflection ?...
You can get the TypeConverter to do this for you; I'll knock up a demo...
would this be the same as !IsClass&&!IsInterface&&!IsPrimitive ?
Well, I'd go for Type.IsValueType

Marc
Jun 27 '08 #2
Et voila; an "editable" immutable struct via PropertyGrid

(quoted because it isn't actually an edit; it is a create)

Marc

using System.ComponentModel;
using System.Windows.Forms;

[TypeConverter(typeof(SomeStructConverter))]
public struct SomeStruct
{
private readonly int foo;
private readonly string bar;

public int Foo { get {return foo;}}
public string Bar { get {return bar;}}

public SomeStruct(int foo, string bar)
{
this.foo = foo;
this.bar = bar;
}
public override string ToString()
{
return string.Format("{0}:{1}", Foo, Bar);
}
}

sealed class SomeStructConverter : ExpandableObjectConverter
{
public override bool
GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return true;
}
public override object CreateInstance(ITypeDescriptorContext
context, System.Collections.IDictionary propertyValues)
{
return new SomeStruct((int)propertyValues["Foo"],
(string)propertyValues["Bar"]);
}

// if you want to be able to edit the text directly
// rather than via the sub-properties, then you need
// to implement [Can]ConvertTo / [Can]ConvertFrom looking for
// string; note that ConvertTo will use ToString by
// default, so you just need [Can]ConvertFrom
}

class SomeType
{
private SomeStruct someValue;
public SomeStruct SomeValue
{
get { return someValue; }
set { someValue = value; }
}
}

static class Program
{
static void Main()
{
Application.EnableVisualStyles();
using (Form form = new Form())
using (PropertyGrid grid = new PropertyGrid())
{
grid.Dock = DockStyle.Fill;
form.Controls.Add(grid);
grid.SelectedObject = new SomeType();
Application.Run(form);
}
}
}
Jun 27 '08 #3
Here you go; a mock up, just showing a possible setup... actually I
switched to TypeDescriptor for the properties here for brevity, but in a
real system I'd probably use ICustomTypeDescriptor /
TypeDescriptionProvider...

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;

[TypeConverter(typeof(FlexiObjectConverter))]
class FlexiObject
{
private readonly Dictionary<string, objectvalues
= new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

internal IEnumerable<KeyValuePair<string, object>Values
{
get { return values; }
}

public object this[string key]
{
get
{
object value;
values.TryGetValue(key, out value);
return value;
}
set
{
if (value == null)
{
values.Remove(key);
}
else
{
values[key] = value;
}
}
}
}
class FlexiObjectConverter : TypeConverter
{
public override bool GetPropertiesSupported(ITypeDescriptorContext
context)
{
return true;
}
public override PropertyDescriptorCollection
GetProperties(ITypeDescriptorContext context, object value, Attribute[]
attributes)
{
FlexiObject obj = (FlexiObject)value;
List<PropertyDescriptorprops = new List<PropertyDescriptor>();
foreach (KeyValuePair<string, objectpair in obj.Values)
{
if (pair.Value != null)
{
props.Add(new
FlexiPropertyDescriptor(pair.Value.GetType(), pair.Key));
}
}
return new PropertyDescriptorCollection(props.ToArray(), true);
}
}
class FlexiPropertyDescriptor : PropertyDescriptor
{
private readonly Type propertyType;
public FlexiPropertyDescriptor(Type propertyType, string name)
: base(name, new Attribute[0])
{
this.propertyType = propertyType;
}
public override bool IsReadOnly
{
get { return false; }
}
private FlexiObject GetFlexi(object component)
{
return (FlexiObject)component;
}
public override object GetValue(object component)
{
return GetFlexi(component)[Name];
}
public override void SetValue(object component, object value)
{
GetFlexi(component)[Name] = value;
}
public override Type ComponentType
{
get { return typeof(FlexiObject); }
}
public override bool CanResetValue(object component)
{
return true;
}
public override void ResetValue(object component)
{
GetFlexi(component)[Name] = GetDefaultValue();
}
public override Type PropertyType
{
get { return propertyType; }
}
public override bool ShouldSerializeValue(object component)
{
return !object.Equals(GetValue(component), GetDefaultValue());
}
private object GetDefaultValue() {
Type type = PropertyType;
if (type == typeof(string)) return "";
if (type.IsValueType) return Activator.CreateInstance(type);
return null;
}
}
static class Program
{
[STAThread]
static void Main()
{
FlexiObject obj = new FlexiObject();
obj["Name"] = "Marc";
obj["DOB"] = DateTime.Today;
obj["ShoeSize"] = 9;
obj["Icon"] = System.Drawing.SystemIcons.Shield;
obj["FavColour"] = System.Drawing.Color.Red;
obj["UriKind"] = System.UriKind.Relative;

Application.EnableVisualStyles();
using (Form form = new Form())
using (PropertyGrid grid = new PropertyGrid())
{
grid.Dock = DockStyle.Fill;
form.Controls.Add(grid);
grid.SelectedObject = obj;
Application.Run(form);
}
}
}
Jun 27 '08 #4
many thanks again :)

I hadnt run into boxing before,
I think I understand it now thanks,
but primitive types dont seem to be affected.

all the structs are just structs,
and I have little control over them.

the data in the structs does need to be edited though thats the whole point
!

the structs could be anywhere such as in an array, or in a class or another
struct.

the defualts however arnt intended to be edited,
well at least not unintentionaly !

ive gone for Type.IsValueType &&!Type.IsPrimitive.

I cant beleive the amount of code thats gone into using this property grid
so far,
I realy wish id made my self a custom cell based control.

rather than create even more code with a type converter,
ive gone for the quick if dirty marshal way.

int size=Marshal.SizeOf(uDefaults.data);
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(uDefaults.data, ptr, true);
udata.data=Marshal.PtrToStructure(ptr, type);
Marshal.FreeHGlobal(ptr);

seems to work even if im a little uneasy about such code.
although it will only work where the struct is initially a null object,
this suits my needs. however editing fields of sub structs doesnt
work with the boxing method, as it seems to create another copy.
seems il have to use a typedreference, but that can only be used for
the struct fields, its a shame it cant be used for the primitive fields too.

Colin =^.^=

"Marc Gravell" <ma**********@gmail.comwrote in message
news:%2*****************@TK2MSFTNGP06.phx.gbl...
>I have a property grid wich stores the data and the defualt as
objects.

Well, you haven't really explained this setup... and unfortunately the
devil is probably in the detail here... can you add more info?
however once ive set the data to the defualt,
if the data is a struct then any edits change the defualt data as well
wich was unexpected !

I'm guessing that your structs are "mutable" - i.e. you can edit them once
created. This is almost always a big mistake; where "almost" means "it
would take a long discussion to explain some borderline scenarios where it
might just possibly make sense to have a mutable struct". In general,
structs should be /immutable/ - i.e. once created they never change, but
can be replaced (hence the need to provide CreateInstance etc on a
TypeConverter).
>I thought value types were always passed by value,
does this mean an object is actually able to behave
as a pointer to a struct ?

Yes; the term is "box"; when you box a value-type to an object, an object
is created on the managed heap that encapsulates the value-type -
*broadly* as though you had a class with a single field member (although
it isn't really that).

If you then give two different bits of code the same boxed copy, then they
will be stomping all over each others values
>I gues il have to identify if its a struct and copy it with reflection
?...
You can get the TypeConverter to do this for you; I'll knock up a demo...
>would this be the same as !IsClass&&!IsInterface&&!IsPrimitive ?
Well, I'd go for Type.IsValueType

Marc

Jun 27 '08 #5
There is no special reason that primatives aren't affected, except
that they are immutable. That is the key point here:
the data in the structs does need to be edited though
There is a 99.8% change this is a mistake [according to the department
of invented statistics].

structs in C# (or rather: ValueType in .NET) are not the same as
structs in C++; they are not a "light weight object" or however else
people think of them... the difference is the copy vs reference
semantics. I don't know enough to recommend which... but I firmly
believe that you'll have a much easier time of things if you either a:
switch to classes instead of structs, or b: make the structs
immutable.

Marc
Jun 27 '08 #6
Thanks Mark,

Nice example for the reason of the "CreateInstance" method existence, very
cool indeed!


"Marc Gravell" <ma**********@gmail.comwrote in message
news:ON**************@TK2MSFTNGP05.phx.gbl...
Et voila; an "editable" immutable struct via PropertyGrid

(quoted because it isn't actually an edit; it is a create)

Marc

using System.ComponentModel;
using System.Windows.Forms;

[TypeConverter(typeof(SomeStructConverter))]
public struct SomeStruct
{
private readonly int foo;
private readonly string bar;

public int Foo { get {return foo;}}
public string Bar { get {return bar;}}

public SomeStruct(int foo, string bar)
{
this.foo = foo;
this.bar = bar;
}
public override string ToString()
{
return string.Format("{0}:{1}", Foo, Bar);
}
}

sealed class SomeStructConverter : ExpandableObjectConverter
{
public override bool GetCreateInstanceSupported(ITypeDescriptorContext
context)
{
return true;
}
public override object CreateInstance(ITypeDescriptorContext context,
System.Collections.IDictionary propertyValues)
{
return new SomeStruct((int)propertyValues["Foo"],
(string)propertyValues["Bar"]);
}

// if you want to be able to edit the text directly
// rather than via the sub-properties, then you need
// to implement [Can]ConvertTo / [Can]ConvertFrom looking for
// string; note that ConvertTo will use ToString by
// default, so you just need [Can]ConvertFrom
}

class SomeType
{
private SomeStruct someValue;
public SomeStruct SomeValue
{
get { return someValue; }
set { someValue = value; }
}
}

static class Program
{
static void Main()
{
Application.EnableVisualStyles();
using (Form form = new Form())
using (PropertyGrid grid = new PropertyGrid())
{
grid.Dock = DockStyle.Fill;
form.Controls.Add(grid);
grid.SelectedObject = new SomeType();
Application.Run(form);
}
}
}

Jun 27 '08 #7
well I agree the struct v class is confusing thing to get used to.
and the pass by value/ref can be an awkward difference,
its not always the way you want it to be.

it would be expensive to replace all structs with classes,
not only that, the underlying library requires an array of structs for
various things.
especially for vertex data wich is itself a struct containing several
structs,
and has 200,000 instances.

although I dont edit this amount of data with the property editor,
some of the structs are the same type, and this I have little control over,
or would be too inconvenient to have struct and class duplicated.

its hard to use TypedReference however, as you cant use it as a field,
nor can you return it as a function value, you cant even pass it as a ref
nor cast it to anything not even an object or value type.
so you have to use it in the same function, or sub function.

but it does allow you to modify a field of a struct within a struct.
all you need is an array of FieldInfo wich contain the list of nested
members,
and the final fieldinfo, and ofc an object such as a class that holds the
struct.
im not sure how it would work on an aray of structs.
although the class does actually hold a boxed copy of the struct in a
dictionary.

//recursively called
public UData SetField(object value,List<FieldInfosubFfields)
{
....
if(...)
{
List<FieldInfofields = new List<FieldInfo>();
parentUdata = parent.SetField(null, fields);
if (fields.Count 0)
{
fields.Reverse();
TypedReference typedReference =
TypedReference.MakeTypedReference(parentUdata.data , fields.ToArray());
fieldInfo.SetValueDirect(typedReference,value);
return null;
}
fieldInfo.SetValue(parentUdata.data,value);
return null;
}
...
}
Colin =^.^=

"Marc Gravell" <ma**********@gmail.comwrote in message
news:e3**********************************@k13g2000 hse.googlegroups.com...
There is no special reason that primatives aren't affected, except
that they are immutable. That is the key point here:
>the data in the structs does need to be edited though

There is a 99.8% change this is a mistake [according to the department
of invented statistics].

structs in C# (or rather: ValueType in .NET) are not the same as
structs in C++; they are not a "light weight object" or however else
people think of them... the difference is the copy vs reference
semantics. I don't know enough to recommend which... but I firmly
believe that you'll have a much easier time of things if you either a:
switch to classes instead of structs, or b: make the structs
immutable.

Marc

Jun 27 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Shawn B. | last post by:
Greetings, Is it possible to create a custom ValueType object in C#? Or must I use managed C++ for that? Thanks, Shawn
4
by: Brian Brane | last post by:
I have properties that wrap DataRow columns as in: public int aNumber { get{ return m_DataRow; } set{ m_DataRow = value; } } If the column happens to contain DBNull, I get a cast exception...
2
by: Eric Newton | last post by:
Since String.Format has to box all value types to accomodate the params, and just for sheer efficiency, are there possibly any plans for a FormatValue method to minimize boxing? public static...
6
by: Sahil Malik | last post by:
Okay, I can't inherit from System.ValueType. Why this restriction?? What I am trying to acheive is, create my own ValueType called "Money". So if I have a decimal that has value 1.93991, when...
6
by: Aryeh Holzer | last post by:
Let me start with a quote from the C# Programmers Reference (where I learned the cool word "covariance"): "When a delegate method has a return type that is more derived than the delegate...
1
by: INeedADip | last post by:
PropertyInfo props = obj.GetType().GetProperties(); foreach (PropertyInfo p in props) if (p.PropertyType is ValueType) this._commonProperties.Add(p.Name, p.GetValue(request, null).ToString()); ...
6
by: Manikkoth | last post by:
Hello, Just curious to see why ValueType (which the base for all value types) is a class. I thought "class" would make a type a reference type. However, IsValueType for ValueType is returning...
1
by: Tony Johansson | last post by:
Hello! Everything not derived from System.ValueType is a reference type. I just wonder this ValueType type is derived from Object and it overrides the two methods Equals and GetHashCode which...
2
by: Veeranna Ronad | last post by:
Hello, Our application gets datetime from an interface function. This function returns "ValueType". How to copy datetime content from this "ValueType" to DateTime variable? Thanks in advance...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.