Note: My question has several parts to it. I'd appreciate it if you would please answer each of the questions, instead of simply telling me what to do to get this to compile. :)
I'm not by any means good with C#. In fact, the reason why I don't know much about it is my class is focused on making efficient Algorithms and not really on teaching us .NET. Nevertheless all of our programs must be written in .NET and it hasn't been a problem until just now. I have the following code, but it won't compile and I don't really understand why. I have a gut feeling that this should be rewritten altogether, but before I do that, I want to know WHY this isn't allowed.
The point of the struct is to create a linked list like structure so I can add another node to the end of the "list" and then traverse and recall the nodes in reverse order
private struct BackPointer
{
public BackPointer previous;
public string a;
public string b;
public BackPointer(BackPointer p, string aa, string bb)
{
previous = p;
a = aa;
b = bb;
}
}
then later in my code I have something to the effect of
BackPointer pointer = new BackPointer();
pointer = new BackPointer(pointer, somestring_a, somestring_b);
The compile error I'm getting is Struct member 'MyClass.BackPointer.previous' of type 'MyClass.BackPointer' causes a cycle in the struct layout
This seems to be an obvious error. It doesn't like the fact that I am passing in the struct in the constructor of the same struct. But why is that not allowed? I would imagine this code would just create a new node in the list and return this node with a pointer back to the previous node, but apparently that's not what would happen. So what would actually happen then? Lastly what is the recommended way to resolve this? I was thinking to just tell it to be unmanaged just handle my pointers manually, but I only really know how to do that in C++. I don't really know what could go wrong in C#
That's not a pointer; it's an actual embedded struct value.
The whole point of structs is that they're (almost) never pointers.
You should use a class instead.
But why is that not allowed?
It's a struct - a value type. That means wherever you've got a variable of that type, that variable contains all the fields within the struct, directly inline. If something contains itself (or creates a more complicated cycle) then you clearly can't allocate enough space for it - because it's got to have enough space for all its fields and another copy of itself.
Lastly what is the recommended way to resolve this?
Write a class instead of a struct. Then the value of the variable will be a reference to an instance, not the data itself. That's how you get something close to "a pointer" in C#. (Pointers and references are different, mind you.)
I suggest you read my article on value types and reference types for more information - this is an absolutely critical topic to understand in C#.
Backpointer HAS to exist before creating a Backpointer, because you can't have a Backpointer without another Backpointer (which would then need another Backpointer and on and on). You simply can't create a Backpointer based on the way you've created it, because, as a struct, Backpointer can never be null.
In other words, it's impossible to create a Backpointer with this code. The compiler knows that, and so it forces you to make something that would work logically.
Structs are stored by value. In this case, your struct stores within itself another instance of the same struct. That struct stores within itself another struct and so on. Therefore this is impossible. It is like saying that every person in the world must have 1 child. There is no way this is possible.
What you need to use is a class. Classes store by reference, which means that it does not store the class within itself, it only stores a reference to that class.
A CLR struct is by definition a value type. What this means in your context is that the compiler needs to know the exact layout of the type. However, it cannot know how to layout a type which contains an instance of itself - does that sound reasonable? Change the struct to class (which makes your BackPointer to a reference type) and you'll see it's gonna work out of the box. The reason is that an instance of any reference type has always has the same layout - it is basically just a "pointer" to some location of the managed heap. I strongly recommend to read on a bit about the basics of C# or CLI type system.
Related
In c# -> struct, we cannot assign a value to instance field at declaration. Can you tell me the reason? Thanks.
A simple example:
struct Test
{
public int age =10; // it's not allowed.
}
I think the answer is very simple, but hard to get a grasp of if you do not know the difference between value types and reference types.
Maybe something to note is that reference type are held in the heap, which the garbage collect cleans. And a value type lives in the stack. Every time you define a scope, like:
{
}
A new local stack is created. Once you exit this scope, all value types on the stack are disposed unless a reference is held to them on the heap.
Seeing as reference types and value types are very differently handled, they are also designed with these changes in mind. Not being able to have empty constructors and also not being able to assign values on construction is a logical result of this.
I found a very old stackoverflow question regarding the same, they also have some short answers regarding it being designed like that for performance reasons:
Why can't I initialize my fields in my structs?
My source for this info was the ref book for 70-483.
Hope this gave you the clarification you are looking for
I have a code like the following:
struct A
{
void SomeMethod()
{
var items = Enumerable.Range(0, 10).Where(i => i == _field);
}
int _field;
}
... and then i get the following compiler error:
Anonymous methods inside structs can not access instance members of 'this'.
Can anybody explains what's going on here.
Variables are captured by reference (even if they were actually value-types; boxing is done then).
However, this in a ValueType (struct) cannot be boxed, and hence you cannot capture it.
Eric Lippert has a nice article on the surprises of capturing ValueTypes. Let me find the link
The Truth About Value Types
Note in response to the comment by Chris Sinclair:
As a quick fix, you can store the struct in a local variable: A thisA = this; var items = Enumerable.Range(0, 10).Where(i => i == thisA._field); – Chris Sinclair 4 mins ago
Beware of the fact that this creates surprising situations: the identity of thisA is not the same as this. More explicitly, if you choose to keep the lambda around longer, it will have the boxed copy thisA captured by reference, and not the actual instance that SomeMethod was called on.
When you have an anonymous method it will be compiled into a new class, that class will have one method (the one you define). It will also have a reference to each variable that you used that was outside of the scope of the anonymous method. It's important to emphasize that it is a reference, not a copy, of that variable. "lambdas close over variables, not values" as the saying goes. This means that if you close over a variable outside of the scope of a lambda, and then change that variable after defining the anonymous method (but before invoking it) then you will see the changed value when you do invoke it).
So, what's the point of all of that. Well, if you were to close over this for a struct, which is a value type, it's possible for the lambda to outlive the struct. The anonymous method will be in a class, not a struct, so it will go on the heap, live as long as it needs to, and you are free to pass a reference to that class (directly or indirectly) wherever you want.
Now imagine that we have a local variable, with a struct of the type you've defined here. We use this named method to generate a lambda, and let's assume for a moment that the query items is returned (instead of the method being void). Would could then store that query in another instance (instead of local) variable, and iterate over that query some time later on another method. What would happen here? In essence, we would have held onto a reference to a value type that was on the stack once it is no longer in scope.
What does that mean? The answer is, we have no idea. (Please look over the link; it's kinda the crux of my argument.) The data could just happen to be the same, it could have been zeroed out, it could have been filled by entirely different objects, there is no way of knowing. C# goes to great lengths, as a language, to prevent you from doing things like this. Languages such as C or C++ don't try so hard to stop you from shooting your own foot.
Now, in this particular case, it's possible that you aren't going to use the lambda outside of the scope of what this refers to, but the compiler doesn't know that, and if it lets you create the lambda it has no way of determining whether or not you expose it in a way that could result in it outliving this, so the only way to prevent this problem is to disallow some cases that aren't actually problematic.
To use a struct, we need to instantiate the struct and use it just like a class. Then why don't we just create a class in the first place?
A struct is a value type so if you create a copy, it will actually physically copy the data, whereas with a class it will only copy the reference to the data
A major difference between the semantics of class and struct is that structs have value semantics. What is this means is that if you have two variables of the same type, they each have their own copy of the data. Thus if a variable of a given value type is set equal to another (of the same type), operations on one will not affect the other (that is, assignment of value types creates a copy). This is in sharp contrast to reference types.
There are other differences:
Value types are implicitly sealed (it is not possible to derive from a value type).
Value types can not be null.
Value types are given a default constructor that initialzes the value type to its default value.
A variable of a value type is always a value of that type. Contrast this with classes where a variable of type A could refer to a instance of type B if B derives from A.
Because of the difference in semantics, it is inappropriate to refer to structs as "lightweight classes."
All of the reasons I see in other answers are interesting and can be useful, but if you want to read about why they are required (at least by the VM) and why it was a mistake for the JVM to not support them (user-defined value types), read Demystifying Magic: High-level Low-level Programming. As it stands, C# shines in talking about the potential to bring safe, managed code to systems programming. This is also one of the reasons I think the CLI is a superior platform [than the JVM] for mobile computing. A few other reasons are listed in the linked paper.
It's important to note that you'll very rarely, if ever, see an observable performance improvement from using a struct. The garbage collector is extremely fast, and in many cases will actually outperform the structs. When you add in the nuances of them, they're certainly not a first-choice tool. However, when you do need them and have profiler results or system-level constructs to prove it, they get the job done.
Edit: If you wanted an answer of why we need them as opposed to what they do, ^^^
In C#, a struct is a value type, unlike classes which are reference types. This leads to a huge difference in how they are handled, or how they are expected to be used.
You should probably read up on structs from a book. Structs in C# aren't close cousins of class like in C++ or Java.
This is a myth that struct are always created on heap.
Ok it is right that struct is value type and class is reference type. But remember that
1. A Reference Type always goes on the Heap.
2. Value Types go where they were declared.
Now what that second line means is I will explain with below example
Consider the following method
public void DoCalulation()
{
int num;
num=2;
}
Here num is a local variable so it will be created on stack.
Now consider the below example
public class TestClass
{
public int num;
}
public void DoCalulation()
{
TestClass myTestClass = new TestClass ();
myTestClass.num=2;
}
This time num is the num is created on heap.Ya in some cases value types perform more than reference types as they don't require garbage collection.
Also remeber:
The value of a value type is always a value of that type.
The value of a reference type is always a reference.
And you have to think over the issue that if you expect that there will lot be instantiation then that means more heap space yow will deal with ,and more is the work of garbage collector.For that case you can choose structs.
Structs have many different semantics to classes. The differences are many but the primary reasons for their existence are:
They can be explicitly layed out in memmory
this allows certain interop scenarios
They may be allocated on the stack
Making some sorts of high performance code possible in a much simpler fashion
the difference is that a struct is a value-type
I've found them useful in 2 situations
1) Interop - you can specify the memory layout of a struct, so you can guarantee that when you invoke an unmanaged call.
2) Performance - in some (very limited) cases, structs can be faster than classes, In general, this requires structs to be small (I've heard 16 bytes or less) , and not be changed often.
One of the main reasons is that, when used as local variables during a method call, structs are allocated on the stack.
Stack allocation is cheap, but the big difference is that de-allocation is also very cheap. In this situation, the garbage collector doesn't have to track structs -- they're removed when returning from the method that allocated them when the stack frame is popped.
edit - clarified my post re: Jon Skeet's comment.
A struct is a value type (like Int32), whereas a class is a reference type. Structs get created on the stack rather than the heap. Also, when a struct is passed to a method, a copy of the struct is passed, but when a class instance is passed, a reference is passed.
If you need to create your own datatype, say, then a struct is often a better choice than a class as you can use it just like the built-in value types in the .NET framework. There some good struct examples you can read here.
I was wondering, why can't I overload '=' in C#? Can I get a better explanation?
Memory managed languages usually work with references rather than objects. When you define a class and its members you are defining the object behavior, but when you create a variable you are working with references to those objects.
Now, the operator = is applied to references, not objects. When you assign a reference to another you are actually making the receiving reference point to the same object that the other reference is.
Type var1 = new Type();
Type var2 = new Type();
var2 = var1;
In the code above, two objects are created on the heap, one referred by var1 and the other by var2. Now the last statement makes the var2 reference point to the same object that var1 is referring. After that line, the garbage collector can free the second object and there is only one object in memory. In the whole process, no operation is applied to the objects themselves.
Going back to why = cannot be overloaded, the system implementation is the only sensible thing you can do with references. You can overload operations that are applied to the objects, but not to references.
If you overloaded '=' you would never be able to change an object reference after it's been created.
... think about it - any call to theObjectWithOverloadedOperator=something inside the overloaded operator would result in another call to the overloaded operator... so what would the overloaded operator really be doing ? Maybe setting some other properties - or setting the value to a new object (immutability) ?
Generally not what '=' implies..
You can, however, override the implicit & explicit cast operators:
http://www.blackwasp.co.uk/CSharpConversionOverload.aspx
Because it doesn't really make sense to do so.
In C# = assigns an object reference to a variable. So it operates on variables and object references, not objects themselves. There is no point in overloading it depending on object type.
In C++ defining operator= makes sense for classes whose instances can be created e.g. on stack because the objects themselves are stored in variables, not references to them. So it makes sense to define how to perform such assignment. But even in C++, if you have set of polymorphic classes which are typically used via pointers or references, you usually explicitly forbid copying them like this by declaring operator= and copy constructor as private (or inheriting from boost::noncopyable), because of exactly the same reasons as why you don't redefine = in C#. Simply, if you have reference or pointer of class A, you don't really know whether it points to an instance of class A or class B which is a subclass of A. So do you really know how to perform = in this situation?
Actually, overloading operator = would make sense if you could define classes with value semantics and allocate objects of these classes in the stack. But, in C#, you can't.
One possible explanation is that you can't do proper reference updates if you overload assignment operator. It would literally screw up semantics because when people would be expecting references to update, your = operator may as well be doing something else entirely. Not very programmer friendly.
You can use implicit and explicit to/from conversion operators to mitigate some of the seeming shortcomings of not able to overload assignment.
I don't think there's any really particular single reason to point to. Generally, I think the idea goes like this:
If your object is a big, complicated object, doing something that isn't assignment with the = operator is probably misleading.
If your object is a small object, you may as well make it immutable and return new copies when performing operations on it, so that the assignment operator works the way you expect out of the box (as System.String does.)
You can overload assignment in C#. Just not on an entire object, only on members of it. You declare a property with a setter:
class Complex
{
public double Real
{
get { ... }
set { /* do something with value */ }
}
// more members
}
Now when you assign to Real, your own code runs.
The reason assignment to an object is not replaceable is because it is already defined by the language to mean something vitally important.
It's allowed in C++ and if not careful , it can result in a lot of confusion and bug hunting.
This article explains this in great detail.
http://www.relisoft.com/book/lang/project/14value.html
Because shooting oneself in the foot is frowned upon.
On a more serious note one can only hope you meant comparison rather than assignment. The framework makes elaborate provision for interfering with equality/equivalence evaluation, look for "compar" in help or online with msdn.
Being able to define special semantics for assignment operations would be useful, but only if such semantics could be applied to all situations where one storage location of a given type was copied to another. Although standard C++ implements such assignment rules, it has the luxury of requiring that all types be defined at compile time. Things get much more complicated when Reflection and and generics are added to the list.
Presently, the rules in .net specify that a storage location may be set to the default value for its type--regardless of what that type is--by zeroing out all the bytes. They further specify that any storage location can be copied to another of the same type by copying all the bytes. These rules apply to all types, including generics. Given two variables of type KeyValuePair<t1,t2>, the system can copy one to another without having to know anything but the size and alignment requirements of that type. If it were possible for t1, t2, or the type of any field within either of those types, to implement a copy constructor, code which copied one struct instance to another would have to be much more complicated.
That's not to say that such an ability offer some significant benefits--it's possible that, were a new framework being designed, the benefits of custom value assignment operators and default constructors would exceed the costs. The costs of implementation, however, would be substantial in a new framework, and likely insurmountable for an existing one.
This code is working for me:
public class Class1
{
...
public static implicit operator Class1(Class2 value)
{
Class1 result = new Class1();
result.property = value.prop;
return result;
}
}
Type of Overriding Assignment
There are two type to Override Assignment:
When you feel that user may miss something, and you want force user to use 'casting'
like float to integer, when you loss the floating value
int a = (int)5.4f;
When you want user to do that without even notice that s/he changing the object type
float f = 5;
How to Override Assignment
For 1, use of explicit keyword:
public static explicit override ToType(FromType from){
ToType to = new ToType();
to.FillFrom(from);
return to;
}
For 2, use of implicit keyword:
public static implicit override ToType(FromType from){
ToType to = new ToType();
to.FillFrom(from);
return to;
}
Update:
Note: that this implementation can take place in either the FromType or ToType class, depending on your need, there's no restriction, one of your class can hold all the conversions, and the other implements no code for this.
In a recent project I was working I created a structure in my class to solve a problem I was having, as a colleague was looking over my shoulder he looked derisively at the structure and said "move it into a class".
I didn't have any argument for not moving it into a class other than I only need it in this class but this kind of falls down because couldn't I make it a nested class?
When is it ok to use a structure?
You should check out the value type usage guidelines: http://msdn.microsoft.com/en-us/library/y23b5415(vs.71).aspx
The article lists several important points but the few that I feel are the most valuable are the following
Is the value immutable?
Do you want the type to have value semantics?
If the answer to both questions is yes then you almost certainly want to use a Structure. Otherwise I would advise going with a class.
There are issues with using structures with a large amount of members. But I find that if I consider the two points above, rarely do I have more than the recommended number of members / size in my value types.
MSDN has a good guidelines document to cover structure usage. To summarize:
Act like primitive types.
Have an instance size under 16 bytes.
Are immutable.
Value semantics are desirable.
Otherwise, use a class.
You should always use a Class as your first choice, changing to Structure only for very specific reasons (as others have already outlined).
Depending on how much you "only need it in this class", you might be able to avoid the nested type completely by using an anonymous type; this will only work within a single method:
Public Class Foo
Public Sub Bar
Dim baz = New With { .Str = "String", .I = 314 }
End Sub
End Class
you can't (readily--there are a few things you can do with generics) move the instance baz outside of the Sub in a typesafe manner. Of course an Object can hold anything, even an instance of an anonymous type.
I think structures are great if you need copy the object or do not want it to be modified by the passed function. Since passed functions can not modify the originally passed structure instead got a new copy of it, this can be a life saver. (unless they passed as ByRef obviously) and can save you trouble of deep copy craziness in .NET or implementing pain of an ICloneSomething implementation.
But the general idea is defining a custom data structure in a more semantic way.
About moving to a class, if you are moving into a class where it'll be part of a class, generally this is good practice since your structure is 99% of the time related with one of you classes not related with a namespace.
If you are converting it to a class then you need to consider "is it defining a data strcuture" and "is it expensive?" since it's gonna be copied all over the place, "do you want to get affected by modifications done by the passers?"
The usage guidelines referenced by Marc and Rex are excellent and nicely cover cases where you aren't sure which one you would want. I will list some use cases where use of a struct is a requirement.
When you need to set the layout of the fields in memory
Interop with unmanaged code.
When you want to make Unions.
You need a fixed size buffer inlined.
You want to be able to do the equivalent of a reinterpret_cast with relative safety (so long as the struct does not contain any fields which are themselves reference types.
These are normally edge cases and (with the exception of interop) not recommended practices unless their use is necessary for the success of the project/program.