Get all values of premade struct? C# - c#

In C# I have a VERY huge struct, and I want to iterate through it easily, instead of manually typing them.
I tried using:
Type structType = typeof(myStruct);
System.Reflection.FieldInfo[] fields = structType.GetFields();
for(int i=0; i<fields.Length-1; i++)
{
richTextBox1.Text += fields[i].Name + "\n";
}
where myStruct is the huge struct, but you can't pass variable structs to that, only the structs them selves.
Basically what I want to do is:
public struct myStruct
{
public string myName;
public int myAge;
...
...
}
//in code
myStruct a = readStructFromFile( filename );
string text = "";
foreach(field in a)
{
text += field.name + ": " + file.value;
}
That possible?

Use FieldInfo.GetValue. Bigger structs really should be classes since structs are meant to be small.
myStruct a = readStructFromFile( filename );
Type structType = typeof(myStruct);
System.Reflection.FieldInfo[] fields = structType.GetFields();
var builder = new StringBuilder();
foreach(var field in fields)
{
builder.Append(string.Format("{0} {1}\n",
field.Name,
field.GetValue(a).ToString());
}
richTextBox1.Text += builder.ToString();

My recommendation would be to write some simple code-generation routines to generate something close to the code you want and copy it to the clipboard. Then paste it into your program and make whatever little tweaks are required.
Having to write large amounts of boilerplate code usually implies a design deficiency either in what you're doing or in the language/framework you're using. Depending upon exactly what you're doing, the fault could be in either the former or the latter.
There are situations where large structures are appropriate; if each variable of some type is supposed to encapsulate a fixed collection of independent values, an exposed-field structure expresses that perfectly. Until things start getting so big as to create a risk of stack overflow, the factors which favor using a 4-field structures over a 4-field class will be even more significant with a 20-field structure versus a 20-field class.
There are some definite differences between programming with structures versus programming with classes. If one uses immutable classes, generating from a class instance a new instance which is identical except for a few fields is difficult. If one uses mutable classes, it can be difficult to ensure that every variable encapsulates its own set of independent values. Suppose one has a List<classWithPropertyX> myList, and myList[0] holds an instance where X is 3. One wishes to have myList[0] hold an instance where X is 4, but not affect the value of the X property associated with any other variable or storage location of type classWithPropertyX.
It's possible that the proper approach is
myList[0].X = 4;
but that could have unwanted side-effects. Perhaps one needs to use
myList[0] = myList[0].WithX(4);
or maybe
var temp = myList[0];
myList[0] = new classWithPropertyX(temp.this, 4, temp.that, temp.theOther, etc.);
One may have to examine a lot of code to ascertain with certainty which technique is appropriate. By contrast, if one has a List<structWithExposedFieldX> myList the proper code is:
var temp = myList[0];
temp.X = 4;
myList[0] = temp;
The only information one needs to know that's the correct approach is the fact that structWithExposedFieldX is a struct with an exposed public field X.

Related

LINQ Select Many - Modify flattened collection

I have a class named ACTIVITY. This class contains a list of Laps, and each Lap has a collection of TRACPOINTS.
ACTIVITY --many--> LAPS ---many --> TRACPOINTS.
Whenever I fLatten the TRACPOINTS collection I get the list of all the TRACPOINTS. But when I modify those of course the originals don't get modified since it's a copy.
Is there any way that whatever change I made to the flattened tracpoints gets changed in the Tracpoints list for each lap?
As long as TRACPOINT is a struct, it is not possible in any reasonable way.
Whenever you assign a value of struct variable or field to another variable or field, its contents are copied. The same holds for passing it as a method argument or returning it from a method, its value is copied. This is value semantics [1]. Compare this to atomic types like int, which have value semantics too. You would probably expect the following code to print 2, not 3.
static function Change(int j) { j = 3; }
static void Main(string[] args) {
int i = 2;
Change(i);
System.Console.WriteLine(i);
}
If you do SelectMany, each value from the collection is probably assigned to some temporary local variable and then returned from the iterator (SelectMany), therefore it is copied and in fact possibly copied many times before it comes out from the iterator. So what you are updating is a copy of the struct. Like in the example, you're not changing variable i, but its copy stored in variable j.
This is why structs should be immutable. Instead of having properties with getters and setter in your struct, they should have only getters. For changing values of properties of a struct, you can implement methods that copy the whole original struct, change the value of the desired property and return the new struct instance. In fact, again, its copy will be returned. Example:
struct S {
int f;
public int F { get { return this.f; } }
public S SetF(int newVal) {
var s = new S();
s.f = newVal;
return s;
}
}
var x = new S();
x = x.SetF(30);
That said, it could be possible to achieve what you want with pointers and unsafe C#, but believe me, it will be way easier to change your structs to classes, so that they have reference semantics instead of value semantics, or keep them structs, but make them immutable and do not use Linq, but old school loops. If you want to use Linq for something like SelectMany in such scenario, you probably do not care about performance difference between structs and classes so much...
[1] http://msdn.microsoft.com/en-us/library/aa664472(v=vs.71).aspx

Allocation of value types

When you assign an instance of a value type to another instance, the object is copied bit-by-bit to the target location:
private struct Word
{
public Word(char c) { ... }
}
public void Method(Word a)
{
Word b = a; //a is copied and stored in b
}
But given the following code:
private Word _word;
public void Method() {
_word = new Word('x');
}
I suspect that the right-hand side (RHS) expression is evaluated first - which instantiates a value type on the stack - and then the value is copied and stored on the location of the _word field, which is on the heap.
The alternative would be to take the left-hand side into consideration, and instantiate the value type directly on _word, avoiding having to copy the object.
Is my suspicion correct? If it is, I suppose it's safe to assume that the first block of code would perform better than the second.
//1 instantiation + 10k copies
Word[] words = new Word[10000];
Word word = new Word('x');
for (int i = 0; i < 10000; i++)
words[i] = word;
//10k instantiations + 10k copies
Word[] words = new Word[10000];
for (int i = 0; i < 10000; i++)
words[i] = new Word('x');
Note: I'm not trying to micro-optimize anything.
Edit: The core of my question is, as Lee puts it: Are structs allocated in place directly, or do they need to be allocated then copied?
When you assign an instance of a value type to another instance, the object is copied bit-by-bit to the target location
When you assign an instance of a value type to a variable of the same type, the value is copied to the target location, yes. But that is true of reference types as well: the reference is copied bit by bit to the target location. The referent of course stays right where it is.
I suspect that the right-hand side (RHS) expression is evaluated first
The specification states that the left hand side is evaluted to produce a variable, then the right hand side is evaluated to produce a value, and then the assignment happens.
In the examples you give the evaluation of the left hand side does not produce an observable side effect and therefore its evaluation can be re-ordered by the optimizers in the C# compiler, the jitter or the CPU if any of them so choose. But if you had something like
x[i++] = v();
then the side effect on the left hand side has to happen before the call on the right hand side.
The core of my question is: Are structs allocated in place directly, or do they need to be allocated then copied?
The specification states that structures are allocated in a temporary location -- which would typically be the stack or a register in practice -- and then copied to their final destination. However, there are some situations in which the optimizer can determine that it is impossible for the user to notice if the mutation happens "in place" at the final destination. This is a copy elision optimization, and the C# compiler will perform this optimization if it feels it can get away with it.
For more details see my article on the subject:
http://ericlippert.com/2010/10/11/debunking-another-myth-about-value-types/
Are either preferred?
What is the business case for multiple identical structs?
If you need multiple identical objects is a struct the best choice?
A struct (re)initialized in that manner is probably not a good solution for the example use case
In the new array the WordStruct is allocated and initialized using the default ctor (no ctor)
You don't have the option to initialize a struct array with another ctor
If you do need identical structs then this would be preferred
WordStruct[] WordStructS = new WordStruct[1000];
for (int i = 0; i < WordStructS.Length; i++) { WordStructS[i].C = 'x'; }
If multiple identical objects what you really need to do then consider a class
A class new array is allocated but not yet initialized
You don't waste resources initializing with the default constructor
WordClass[] WordClassS = new WordClass[1000];
for (int i = 0; i < WordClassS.Length; i++) { WordClassS[i] = new WordClass('x'); }
If you want to generalize deep copy of an object (struct or class) then consider IConable
In the case of a struct I suspect it is more efficient than a bit wise copy (but I am not positive)
In the case of class it will make a clone (deep copy) not a reference
public struct WordStruct : ICloneable
{
public char C;
public WordStruct(char C)
{
this.C = C;
}
public object Clone()
{
WordStruct newWordStruct = (WordStruct)this.MemberwiseClone();
return newWordStruct;
}
}
I know in a comment you said curiosity but that is not clear in the question
In the question you state first block of code is preferred over the second
I get it is an interesting question of curiosity
But if it is just curiosity then the question should have stopped at
Is my suspicion correct?

Use of var and default for declaration in C#

Recently I saw a person heavily using var and default keywords for declaration of variables (and for every declaration), something like this:
var employee = default(Employee); //Employee is a class
var errorInfo = default(ErrorInfo); //ErrorInfo is struct; Blank is default value
var salary = default(Double);
var isManager = default(Boolean?);
instead of using:
Employee employee = null; //Employee is a class
ErrorInfo errorInfo = Blank; //ErrorInfo is struct; Blank is default value
Double salary = 0.0;
Boolean? isManager = null;
or, instead of using even:
Employee employee; //Employee is a class
ErrorInfo errorInfo; //ErrorInfo is struct; Blank is default value
Double salary;
Boolean? isManager;
Now using var and default for declaration for every variable is something i am not accustomed to.
Want to know:
- If this is a recommended practice?
- Your views and preference?
PS:
- Have gone through Use of var keyword in C#, Use of "var" type in variable declaration and https://stackoverflow.com/questions/633474/c-do-you-use-var, however, think that this question although related is slightly different as it is solely around declaration/initialization and not around assignment.
- I understand the difference between snipped 2 and snippet 3. However, question is more around snippet 1.
- If you strongly feel that this question belongs to programmers stackexchange feel free to move.
I'm not going to say anything about "var" there have been comments and discussions about this in the past (sufficiently so ;-)
Concerning "default()" I would not use this to initialize a known type, but rather only in generics. There it helps to transparently handle value types or reference types by allowing you to provide a default (return) value or can be used in comparisons.
Well, the default keyword isn't the most used keyword I think, and in my opinion it serves its purpose best in terms of Generics, like so:
public class Foo<T>{
private T _instance;
public Foo<T>(){
_instance = default(T);
}
}
in order to get a new default instance of T.
There are really no reasons to use it like scenario 1 in your post.
Using var however is a different question, and many view this as a matter of readability. I default to var when I write code simply because I find it easier to read:
var me = new Person();
It seems a bit redundant in terms of readability to do
Person me = new Person();
Another case I recommend var is if something changes. Consider the following example:
public decimal Calculate(decimal one, decimal two){
return one + two;
}
And somewhere else in your code:
decimal d = Calculate(1M, 2M);
If you for some reason change the return type of Calculate to, say, double you need to change all the places where you strongly defined the variable.
If you instead do
var d = Calculate(1M, 2M)
you don't have to worry about this. The Double/Decimal example is a bit simple, but in terms of refactoring and interfacing out classes, I've found this very useful.
I think this is bad practice which will prevent the compiler (and 3rd party tools) from catching bugs related to failure to initialize a variable. Generally I try to keep declaration and assignment as close to each other as possible. Assigning values that aren't intended to be used to variables can potentially introduce subtle bugs that are difficult to catch. Normally I'd either:
SomeType variable1; //want to store something that will be out of scope later
using(blah)
{
//...
variable1=blah;
}
//use variable1 here
or assign required value immediately:
SomeType variable2 = new SomeType();
//use variable2 immediately
or (for me, more frequently nowdays)
var variable2 = new SomeType();
assigning null/placeholder values is mainly pointless.
I use var for assignment. However I always declare instances using the class. I generally also instantiate them at the time to avoid unexpected NullReferenceExceptions
The code is ok.
Just make sure that you don't copy this technique to initialize enums where 0 is not default value or flagged enumerations.
[Flags]
public enum MyFlags
{
Test = 1,
Test2 = 2
}
MyFlags flags = default(MyFlags);
Console.WriteLine(flags); // oops

Not able to modify object of struct in loop

I have a List of structure.In the loop i am trying to modify the object's property,which is happening,but when i (Quick look in Visual studio)look into the list object ,the new value is not reflecting.Is it by virtue that the structure's object cannot be modified when in a collection?
I am using generics list with the struct as the type in the list
You mention "modify the object's property" in the context of a struct, but importantly a struct is not an object. Other people have answered as to the issue with structs being copied (and changes discarded), but to take that further the real problem here is that you have a mutable (changeable) struct at all. Unless you are on XNA (or similar) there is simply no need.
If you want to be able to change properties, make it a class:
public class Foo {
public string Bar {get;set;}
}
This is now a reference-type, and your changes (obj.Bar = "abc";) will be preserved through the foreach. If you really want/need a struct, make it immutable:
public struct Foo {
private readonly string bar;
public string Bar { get {return bar; }}
public Foo(string bar) {this.bar = bar;}
}
Now you can't make the mistake of changing the value of a copy; you would instead have to use the indexer to swap the value (list[i] = new Foo("abc");). More verbose (and you can't use foreach), but correct.
But IMO, use a class. Structs are pretty rare, to be honest. If you aren't sure: class.
If you are using a foreach loop you probably got
Compiler Error CS1654
Error Message Cannot modify members of
'variable' because it is a 'read-only
variable type'
This error occurs when you try to
modify members of a variable which is
read-only because it is in a special
construct.
One common area that this occurs is
within foreach loops. It is a
compile-time error to modify the value
of the collection elements. Therefore,
you cannot make any modifications to
elements that are value types,
including structs.
You could however try
struct MyStruct
{
public int i;
}
List<MyStruct> list = new List<MyStruct>
{ new MyStruct { i = 1 }, new MyStruct { i = 2 } };
for(int i = 0; i < list.Count; i++)
{
MyStruct val = list[i];
val.i++;
list[i] = val;
}
EDIT
See also Structs Tutorial
Structs vs. Classes
Structs may seem similar to classes,
but there are important differences
that you should be aware of. First of
all, classes are reference types and
structs are value types.
I THINK i know what the problem might be.
struct Astruct
{
int amember;
}
List < Astruct > listofStructs;
foreach(Astruct A in listofStructs)
{
A.amember = 1337;
}
if this is what you are doing...
when you use structs in c# they are not referenced but copied! so that means the contents of your list is being COPIED to A, so when you change A it doesn't change the value in the list!
to solve this problem (if this is your problem...) either use CLASSES rather than STRUCTS, that way A would be a reference, OR use a manual iterating for loop instead, ie:
for(int i=0;i < listofStructs.Count;i++)
{
listofStructs[i].amember = 1337;
}
alternatively, if you’re using a list, you maybe should use an iterator or something... but the above should definitely fix that problem.
Given the information in your post (although I'd have liked to see the code itself), let me put forth the most probable issue and its fix.
foreach(var s in listOfStructs)
{
s.Property = x;
}
s is assigned to a copy of the actual struct in the collection. s.set_Property is now modifying the copy which is thrown away at the end of the current iteration.
This is because 2 value type variables cannot point to the same instance.
struct1 = new MyStruct(100, 200);
struct2 = struct1; // struct2 is now a copy of struct1
Now to the problem of how do you modify the instances in a collection:
Get the object to modify in a local variable (copy created). Modify it. Now remove the original object and insert the copy. use listOfStructs[i] = modifiedInstance.

Returning a value type from a property

I'm getting confused with what happens on the stack and heap in respect to value type properties in classes.
My understanding so far:
When you create a class with a structure (value type) like this:
class Foo
{
private Bar _BarStruct;
public Bar BarStruct
{
get {return _BarStruct; }
set {_BarStruct = value; }
}
}
private struct Bar
{
public int Number;
Bar()
{
Number = 1;
}
Bar(int i)
{
Number = i;
}
}
If you create a class instance like so:
Foo fooObj = new Foo();
The stack and heap will look like this:
...where the Bar structure is embeded in the Foo class in the heap. This makes sense to me, but I start to loose it when we consider modifying the Number integer in the BarStruct class, within the Foo Object. For example:
Foo fooObj = new Foo();
fooObj.BarStruct.Number = 1;
As I understand, this should be returning a copy of BarStruct to live on the stack, which means that any changes of a member of BarStruct would not be carried through to the object, which is why the last line above gives an error.
Is this right so far?
If so, my question is, how come an assignment such as this:
fooObj.BarStruct = new Bar(2);
...is valid and changes the heap value? Surely this is just changing the value on the stack?? Also, (by and by) I find it so confusing that you are able to use new on a value type. To me, new is for allocatting on the heap (as per C++) and feels unnatural to be doing this for items on the stack.
So just to re-iterate the question, Am I correct in my assumption of what happens when a property containing a structure is called and why can you assign a new structure to a copy and yet it still changes the reference on the heap?
Really hope this all make sense.
Yell if you need clarification!
Ta,
Andy.
Looking at this assignment:
fooObj.BarStruct = new Bar(2);
The assignment isn't changing the value on the stack - it's calling the setter for the property.
In other words, whereas your first assignment is equivalent to:
fooObj.get_BarStruct().Number = 1; // Bad
the second is equivalent to:
fooObj.set_BarStruct(new Bar(2));
Does that help?
Note that the problematic assignment becomes a non-issue if you make your value type immutable to start with - which helps in general, in fact. Mutable value types are a really bad idea in C#; you can get into no end of trouble with them.
In terms of your expectations of "new" - try not to think in C++, basically. C# isn't C++, and various things (destructors, generics, behaviour during construction) will confuse you if you try to effectively write C++ in C#. A "new" statement creates a new instance of a type, whether that's a value type or a reference type.

Categories

Resources