I have a problem with struct during compilation. I program in c# and use Visual Studio 2003. From MSDN:
When you create a struct object using the new operator, it gets created and the appropriate constructor is called. Unlike classes, structs can be instantiated without using the new operator. If you do not use new, the fields will remain unassigned and the object cannot be used until all of the fields are initialized.
You can instantiate a struct without new() statement; on my pc it works perfectly while on another pc I see compiling errors (new() required).
Is there some filter or flag on the Visual studio's environment (like TreatWarningsAsErrors) that can generate this behavior?
an example:
using System;
using System.Collections;
namespace myApp.Utils
{
....
public struct StructParam
{
public int iIndex;
public int[] iStartNoteArray;
public int[] iFinalNoteArray;
public int[] iDimension;
public int[] iStartSequence;
public ArrayList m_iRowIncValueArray;
};
....
}
--------------------------------------------------------------
--------------------------------------------------------------
using System;
using System.Collections;
using myApp.Utils;
namespace myApp.Main
{
....
public class frmMain : System.Windows.Forms.Form
{
....
static void Main()
{
....
StructParam oStructParam;
oStructParam.iIndex = 0;
oStructParam.iStartNoteArray = new int[]{0, 0};
oStructParam.iFinalNoteArray = new int[]{0, 0};
oStructParam.iDimension = new int[]{0, 0};
oStructParam.iStartSequence = new int[]{0, 0};
oStructParam.m_iRowIncValueArray = new ArrayList();
ArrayList myArray = new ArrayList();
myArray.Add(oStructParam);
....
}
.....
}
....
}
I don't think the problem is in code but in some Visual Studio's environment variable.
To use a struct without calling new, you must assign all its members first.
For example,
struct Point
{
public int x;
public int y;
public int DoSomething() { return x * y; }
}
Point p;
p.x = 1;
p.y = 2;
p.DoSomething();
Notice x and y here are fields, NOT properties. You must assign all fields before making use of the struct. If you were to include an auto-property, for example, where you didn't have access to the underlying field, then it would not be possible.
Related
I have to take this to a program that can handle a Double linked list, but I am very new to C# and windows forms. I have the following code so far.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace doublelinkedtest
{
public class nodetoDBList
{
public object elements;
public nodetoDBList prev;
public nodetoDBList next;
public nodetoDBList (int temp)
{
elements = temp;
next = null;
}
public void inserToList(object elements)
{
nodetoDBList newLink;
newLink = new nodetoDBList (elements);
}
}
}
But now I get the following error:
Argument 1: Cannot convert from 'object' to 'int'.
Why do I get this error?. I am only referencing the variable, I am not converting it.
I am very new to C#. And as you can see I am taking this project step by step in order to achieve a double linked list project. Please Help!.
You're calling the nodeToDBList constructor (which takes an int) with an object instead:
public nodetoDBList (int temp) <- Constructor takes an int
{
elements = temp;
next = null;
}
public void inserToList(object elements)
{
nodetoDBList newLink;
newLink = new nodetoDBList (elements); <- passing in an object instead
}
Since elements is declared as an object, and it's an object in the insertToList method, odds are you should modify the constructor so that temp is an object instead of an int.
Say I have this C# class
public class MyClass {
int a;
int[] b = new int[6];
}
Now say I discover this class using reflection and while looking at the fields I find that one of them is of type Array (ie: b)
foreach( FieldInfo fieldinfo in classType.GetFields() )
{
if( fieldInfo.FieldType.IsArray )
{
int arraySize = ?;
...
}
}
I know it's not guaranteed that the array has a field initializer that creates the array but if it does I would like to know the size of the array created by the field initializer.
Is there a way to call the field initializer ?
If there was I would do something like this:
Array initValue = call field initializer() as Array;
int arraySize = initValue.Length;
The only was I found is to create an instance of the whole class but I would rather not do it like this as it's overkill...
Well, you can't.
The following code:
public class Test
{
public int[] test = new int[5];
public Test()
{
Console.Read();
}
}
will be compiled as:
public class Program
{
public int[] test;
public Program()
{
// Fields initializers are inserted at the beginning
// of the class constructor
this.test = new int[5];
// Calling base constructor
base.ctor();
// Executing derived class constructor instructions
Console.Read();
}
}
So, until you create an instance of the type, there is no way to know about the array size.
I dont think you have an option but to create an instance of the class as it doesnt exist until you do that.
i have recently stumbled upon a project(8-puzzle solver using A* alg) in which some codes are weird to me , because i have never seen the likes of it before .
what does this line mean ? what is this ?!
this[StateIndex]
whats this notation ? i cant undersand it at all !
i posted a sample of the class so that you can see it almost all together .
and one more question , is it not wrong to have a class implemented like StateNode? it used only a constructor to initialize its fields , and yet worst, declared them all public ! should he/she not have implemented Propertise for this task?
public enum Direction
{
Up = 1, Down = 2, Left = 3, Right = 4, UpUp = 5, DownDown = 6, LeftLeft = 7, RightRight = 8, Stop = 9
}
class StateNode
{
public int Parent;
public List<int> Childs;
public Direction Move;
public Direction ParentMove;
public byte[,] State;
public byte Depth;
public byte NullRow;
public byte NullCol;
public StateNode()
{ }
public StateNode(int NewParent, Direction NewMove, Direction ParentMove, byte NewDepth, byte NewNullRow, byte NewNullCol)
{
this.Parent = NewParent;
this.State = new byte[5, 5];
this.Move = NewMove;
this.ParentMove = ParentMove;
this.Depth = NewDepth;
this.NullRow = NewNullRow;
this.NullCol = NewNullCol;
this.Childs = new List<int>();
}
}
class StateTree : List<StateNode>
{
public static long MakedNodes;
public static long CheckedNodes;
public static byte MaxDepth;
public List<int> Successor1(int StateIndex)
{
List<int> RetNodes = new List<int>();
StateNode NewState = new StateNode();
//Up
if (this[StateIndex].NullRow + 1 <= 3 && this[StateIndex].ParentMove != Direction.Up)
{
NewState = ChangeItemState(this[StateIndex], StateIndex, Direction.Up, Direction.Down, Convert.ToByte(this[StateIndex].Depth + 1), this[StateIndex].NullRow, this[StateIndex].NullCol, Convert.ToByte(this[StateIndex].NullRow + 1), this[StateIndex].NullCol);
this.Add(NewState);
RetNodes.Add(this.Count - 1);
StateTree.MakedNodes++;
this[StateIndex].Childs.Add(this.Count - 1);
if (NewState.Depth > StateTree.MaxDepth)
StateTree.MaxDepth = NewState.Depth;
}
//Down
//Left
//Right
return RetNodes;
}
}
In your concrete case it's just access to the element, as it used inside the class that is derived from the List<T>
But it can be also indexer which enables index acces to your class object.
For example declare class like this:
public class ListWrapper
{
private List<int> list = ...
public int this[int index]
{
return list[index];
}
}
and after use it like
var lw = new ListWrapper();
//fill it with data
int a = lw[2]; //ACCESS WITH INDEX EVEN IF THE TYPE IS NOT COLLECTION BY ITSELF
this[StateIndex] is using the current class' indexer property. The indexer property is what allows you to access an element in a collection or list object as if it was an array. For instance:
List<string> strings = new List<string>();
strings.Add("Item 1");
strings.Add("Item 2");
strings.Add("Item 3");
string x = strings[0]; // Returns the first item in the list ("Item 1")
When you want to access the indexer property of your own class, however, you have to preface it with the this keyword. You'll notice that in your example, the StateTree class doesn't implement an indexer property, so that may be adding to your confusion. The reason it works is because StateTree inherits from List<StateNode> which does implement an indexer property.
But don't get confused between classes with indexer properties and arrays. Arrays are a completely different thing, though the syntax is similar. An array is a list of objects which can be accessed by an index. An indexer property is an unnamed property of a single object that acts as an array. So for instance, List<string> has an indexer property, so you can access the items it contains using the same syntax as an array index (as shown in the above example). However, you can still make an array of List<string> objects. So for instance:
List<string> strings1 = new List<string>();
strings1.Add("Item 1.1");
strings1.Add("Item 1.2");
List<string> strings2 = new List<string>();
strings2.Add("Item 2.1");
strings2.Add("Item 2.2");
List<string>[] stringsArray = new List<string>[] { strings1, strings2 };
object result;
result = stringsArray[0]; // Returns strings1
result = stringsArray[0][1]; // Returns "Item 1.2"
result = stringsArray[1][0]; // Returns "Item 2.1"
As far as StateNode goes, there's nothing technically wrong with it, and it's not unusual to have a constructor that initializes all the field values, but it's always better to use properties instead of public fields.
its Indexed Properties in C# .net .
you can check Tutorial : http://msdn.microsoft.com/en-us/library/aa288464(v=vs.71).aspx check here
this[StateIndex] is pointing to an element within the class. Because StateTree inherits from a List<T>, you have a collection that's accessible by index (in this case this[N] where N is the element's index.
this[StateIndex] is how you give a class and indexed property e.g
public class IndexedClass
{
private List<String> _content;
public IndexedClass()
{
_content = new List<String>();
}
public Add(String argValue)
{
_content.Add(argValue);
}
public string this[int index]
{
get
{
return _content[index];
}
set
{
_content[Index] = value;
}
}
}
so now you can do
IndexedClass myIndex = new IndexedClass();
myIndex.Add("Fred");
Console.Writeline(myIndex[0]);
myIndex[0] = "Bill";
Console.Writeline(myIndex[0]);
As for statenode if it's local to the class (a helper) then you could argue it as okay, I don't like it though, another ten minutes work it could be done properly. If it's public in the assembly, then it's not accpetable in my opinion. But that is an opinion.
I need advice on structures.
I have 2 sections of code. The first section is as below:
namespace Project.GlobalVariables
{
class IOCard
{
struct InputCard
{
public string CardNo;
public int BaseAddress;
public int LowerAddress;
public int UpperAddress;
public int[] WriteBitNo = new int[16];
public int[] ReadBitNo = new int[16];
}
static InputCard[] InputCards = new InputCard[5];
public static string ACardNo = InputCards[1].CardNo;
public static string BCardNo = InputCards[2].CardNo;
}
}
The second portion is as below:
private void Form1_Load(object sender, EventArgs e)
{
IOCard.ACardNo = "Card A";
IOCard.BCardNo = "Card B";
MessageBox.Show(IOCard.ACardNo);
MessageBox.Show(IOCard.BCardNo);
}
My plan is to be able to assign and retrieve InputCards component by using IOCard as shown in Form1_Load.
However, when I compile the code, I get the following error.
Error 1 'Project.GlobalVariables.IOCard.InputCard.WriteBitNo': cannot have instance field initializers in structs E:\Programming\New platform\StandardPlatform\StandardPlatform\Project\GlobalVariables.cs 16 26 StandardPlatform
Can someone tell me how to solve the error?
Please advise. Thanks.
Here are the classes that I have attempted to create and use, but failed.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Project.GlobalVariables
{
static class IOCard
{
public const int TotalInputCard = 10;
public const int TotalOutputCard = 10;
public class InputCard
{
public string CardNo = "1";
public int BaseAddress;
public int LowerAddress;
public int UpperAddress;
public int[] WriteBitNo = new int[16];
public int[] ReadBitNo = new int[16];
}
public class OutputCard
{
public string CardNo;
public int BaseAddress;
public int LowerAddress;
public int UpperAddress;
public int[] WriteBitNo = new int[16];
public int[] ReadBitNo = new int[16];
}
public static InputCard[] InputCards = new InputCard[TotalInputCard];
public static OutputCard[] OutputCards = new OutputCard[TotalOutputCard];
public static int X100 = InputCards[0].WriteBitNo[0];
public static int Y100 = OutputCards[0].WriteBitNo[0];
}
}
I tried to use these in the Form_Load, like so:
private void Form1_Load(object sender, EventArgs e)
{
IOCard.X100 = 1;
IOCard.Y100 = 1;
}
No matter how much I have tried to search on the net for answers, I have got nowhere.
Please advise. Thanks.
In C#, a struct value is not a reference to an object in the way a value of a class type is. The value of a struct is the "union" of all the values of the instance fields of the struct.
Now, the default value of a struct type is the value where all those fields have their default values. Since the beginning of C#, the syntax:
new S() // S is a value-type
where S is a struct type, has been equivalent to the default value of that struct. There is no constructor call! This is the exact same value which can (nowadays) also be written
default(S) // S is a value-type
Now, things like
struct S
{
int field = 42; // non-static field with initializer, disallowed!
// ...
}
are illegal (cannot have instance field initializers in structs). They could give the impression that the field of a new S() would be 42, but in fact the field of new S() must be the default value of int (which is zero, distinct from 42).
With this explanation, you also see why it is not possible to create a non-static, zero-parameter constructor for a struct type, in C#.
What's it's trying to say is that when you have InputCards = new InputCard[5]; it will allocate a block of memory 5 times the size of an InputCard structure and set all of its bytes to 0. There is no opportunity to execute the int[] WriteBitNo = new int[16]; and such assignments, so you cannot have them.
Your options are to either manually call an initializer for your structs or make it a class and manually initialize the InputCards array with 5 new instances of InputCard.
You will neither be able to initialize a struct's fields nor define a default constructor to initialize it's fields. After looking at your struct, I recommend you use a class instead. It's not recommended to use a struct for a scenario where you have a bunch of fields.
Try this. Initialize the InputCard with a factory function Create():
namespace Project.GlobalVariables
{
class IOCard
{
struct InputCard
{
public string CardNo;
public int BaseAddress;
public int LowerAddress;
public int UpperAddress;
public int[] WriteBitNo;
public int[] ReadBitNo;
static InputCard Create()
{
return new InputCard()
{
CardNo = string.Empty,
WriteBitNo = new int[16],
ReadBitNo = new int[16]
};
}
}
static InputCard[] InputCards = new InputCard[]
{
InputCard.Create(),
InputCard.Create(),
InputCard.Create(),
InputCard.Create(),
InputCard.Create()
};
public static string ACardNo = InputCards[1].CardNo;
public static string BCardNo = InputCards[2].CardNo;
}
}
Use class instead of structure. Structure is used for small types like Point, which are faster to create on the stack and copy, than to create dynamically and pass by reference.
Not sure about the exception, but i have a solution.
You should not use "struct" for this class, it is too much (and storing too much data). If you define it as "class", the same code would work fine.
Is there a particular reason why you want this to be a struct rather than a class?
If you make it a class, it works just fine.
I want to update an instance with properties of a newly created object at once but not breaking the instance binding to other variables. For eg.
public class MyClass{
public double X;
public double Y;
}
MyClass a = new MyClass(2,1);
MyClass b = a;
MyClass c = new MyClass(1,1);
a = c; //'b' should also be equal to 'a'.
//I dont want to do something like this:
a.Y = c.Y;
a.X = c.X;
In my code, 'b' is actually not accessible anymore because it is binded to some UI, 'a' is my only way through updating 'b'. So after 'a = c' is called, b should have the location of [1,1].
Experimental : please feel free to "blow this out of the water" :) Tested in VS 2010 beta 2 against FrameWork 4.0 and 3.5 (full, not "client" versions).
private class indirectReference
{
// using internal so Loc is not visible outside the class
internal struct Loc
{
public double X;
public double Y;
}
// publicly exposed access to the internal struct
public Loc pairODoubles;
// ctor
public indirectReference(double x, double y)
{
pairODoubles.X = x;
pairODoubles.Y = y;
}
}
// test ...
indirectReference r1 = new indirectReference(33, 33);
indirectReference r2 = r1;
indirectReference r3 = new indirectReference(66, 66);
// in this case the doubles in r2 are updated
r1.pairODoubles = r3.pairODoubles;
You could do something like this:
class Wrapper
{
public Wrapper(Location l)
{
this.L = l;
}
public Location L;
}
Wrapper a = new Wrapper(new Location(2,1));
Wrapper b = a;
Location c = new Location(1,1);
a.L = c;
I'm not sure whether it's really appropriate without more context. Just add a level of indirection.
Don't you think making the MyClass immutable would be a suitable approach?
Or: you should perform some reference counting, through a wrapper.