I am trying to find out the syntax to add a complex object into a list. Here's what I know works:
ComplexObject temp = new ComplexObject() {attribute1 = 5, attribute2 = 6};
ComplexObjectList.Add(temp);
Here's what I'm wanting to do instead:
ComplexObjectList.Add(new ComplexObject(){attribute1 = 5, attribute2 = 6});
I realize that it doesn't work, but is there any other way to add one to my list without creating one before hand? I have no need for temp other than this one function call.
Assume you have this class (main point being must be an accessible constructor and the properties you wish to set must be visible):
public class Point
{
public int X { get; set; }
public int Y { get; set; }
}
And you have this list:
var listOfPoint = new List<Point>();
Then you can, as your second example ponders, do this:
listOfPoint.Add(new Point { X = 13, Y = 7 });
Which is roughly (there are some slight differences, Eric Lippert has some good reads on this) equivalent to your first example:
var temp = new Point { X = 13, Y = 7 };
listOfPoint.Add(temp);
In fact, you could add the point at the time the list is constructed as well:
var listOfPoint = new List<Point>
{
new Point { X = 7, Y = 13 }
};
Now the fact that you say you "realize that it doesn't work" is puzzling because your initializer syntax is correct, so I'm not sure if you're asking before trying it, or if there is an issue with the declaration of your list or your class that is throwing you off. That said, if your first code snippet compiled, technically so should your second.
Your code should work. If not, then the problem is probably in the declaration of ComplexObjectList.
Should be: List<ComplexObject> ComplexObjectList = new List<ComplexObject>();
Also make sure the class properties are public.
Related
I have a c# class that looks like this:
public class MemberData
{
public int meme_ck;
public string meme_name;
public bool meme_active;
public MemberData(int ck2, string name2, bool active2)
{
meme_ck = ck2;
meme_name = name2;
meme_active = active2;
}
}
I have made two arrays out of that class:
private MemberData[] memarray1 = new MemberData[10000];
private MemberData[] memarray2 = new Memberdata[10000];
Over the course of my application I do a bunch of stuff with these two arrays and values change, etc. Member's name or active status may change which results in the ararys becoming different.
Eventually I need to compare them in order to do things to the other one based on what results are kicked out in the first one.
For example, member is de-activated in the first array based on something application does, I need to update array 2 to de-activate that same member.
I am trying to use some database design philosphy with the int CK (contrived-key) to be able to rapidly look up the entry in the other array based on the CK.
Since I can't figure it out I've had to resort to using nested for loops like this, which sucks:
foreach (Memberdata md in memarray1)
{
foreach (Memberdatamd2 in memarray2)
{
if (md.ck = md2.ck)
{
//de-activate member
}
}
}
Is there a better way to do this? I just want to find the index in the second array based on CK when I have the CK value from the first array.
Any other tips or advice you have about structure would be appreciated as well. Should I be using something other than arrays? How would I accomplish this same thing with Lists?
Thanks!
Should I be using something other than arrays?
Yes. Don't use arrays; they are seldom the right data structure to use.
How would I accomplish this same thing with Lists?
Lists are only marginally better. They don't support an efficient lookup-by-key operation which is what you need.
It sounds like what you want is instead of two arrays, two Dictionary<int, MemberData> where the key is the ck.
I totally agree with Eric Lippert's answer above. It is better you do not use Array.
Same thing can be achieved using List<MemberData>. You can use LINQ as well to query your DataStructure.
Following is one of the way just to achieve your result using array
class Program
{
static MemberData[] memarray1 = new MemberData[10000];
static MemberData[] memarray2 = new MemberData[10000];
static void Main(string[] args)
{
for (int i = 0; i < memarray1.Length; i++)
{
memarray1[i] = new MemberData(i + 1, "MemName" + i + 1, true);
memarray2[i] = new MemberData(i + 1, "MemName" + i + 1, true);
}
// SIMULATING YOUR APP OPERATION OF CHANGING A RANDOM ARRAY VALUE IN memarray1
int tempIndex = new Random().Next(0, 9999);
memarray1[tempIndex].meme_name = "ChangedName";
memarray1[tempIndex].meme_active = false;
//FOR YOUR UDERSTADNING TAKING meme_ck IN AN INTEGER VARIABLE
int ck_in_mem1 = memarray1[tempIndex].meme_ck;
//FINDING ITEM IN ARRAY2
MemberData tempData = memarray2.Where(val => val.meme_ck == ck_in_mem1).FirstOrDefault();
// THIS IS YOUR ITEM.
Console.ReadLine();
}
}
What do the square brackets mean in a new expression in C# as follows:
public class MyClass
{
public string Name { get; set; }
}
// ...
var x = new MyClass[0]; // <-- what is this?
This is an array declaration
The use of var just allows the compiler to decide on the type
MyClass[] classArray = new MyClass[0];
The 0 inside the [] indicates that the number of array 'spaces' is 0
var classArray = new MyClass[5];
This will create an array of length 5, and the use of var will allow the compiler to decide on the type, which will be MyClass[]
You can access each place in the array I created above by using indexers, mentioned in another answer, similar to this, let's say MyClass has a property called name with public get and set accessors(stupid example I know)
classArray[1] = new MyClass();
classArray[1].Name = "Daniel's class";
This allows us to access the MyClass object held in the second array placement, this is indexing
We can also create an array like this, let's say that the MyClass has a constructor that takes a string for the Name property
var x = new [] {
new MyClass("Daniels"),
new MyClass("Yours"),
new MyClass("Ours")
};
Forgive me for my bad examples
As in the title.
I know this is possible in other languages - is it in C#?
If the question title isn't clear, i would like something that does (something like) this:
MyClass exampleObject1 = new MyClass(...)
exampleObject1.sort() //sort method detects that value is not being assigned and performs sort in place.
MyClass exampleObject2 = exampleObject1.sort() //method detects assignment and returns new sorted object leaving original untouched.
is this something that's possible without resorting to magic? If it is possible, but in some nasty way, what is that way?
EDIT: for those wanting to see an example where you can do this (in python): here. Note that i caveat it with the issue that it does not always work - but this is only in relation to the way i did it when i answered the question. Now i know more about inspect, and you can get all the information you need from the stack to work out if it is being assigned anywhere or not.
Of course, you definitely shouldn't be doing this, but since the OP is more interested if it could be done for curiosity sake, then here is a snippet of code that demonstrates this capability:
class SomeWeirdClass
{
private bool sortApplied = false;
private List<int> elements;
public IList<int> Elements
{
get
{
if(sortApplied)
{
elements.Sort();
sortApplied = false;
}
return elements;
}
}
public SomeWeirdClass(IEnumerable<int> elements)
{
this.elements = elements.ToList();
}
public SortedWeirdClass Sort()
{
sortApplied = true;
return new SortedWeirdClass(this);
}
public class SortedWeirdClass
{
SomeWeirdClass parent;
internal SortedWeirdClass(SomeWeirdClass parent)
{
this.parent = parent;
}
public static implicit operator SomeWeirdClass(SortedWeirdClass sorted)
{
sorted.parent.sortApplied = false;
var elementCopy = new int[sorted.parent.elements.Count];
sorted.parent.elements.CopyTo(elementCopy);
var result = new SomeWeirdClass(elementCopy);
result.Sort();
return result;
}
}
}
Now using it in a program:
static void Main(string[] args)
{
SomeWeirdClass original = new SomeWeirdClass(new[] { 5, 1, 4, 3, 2 });
Console.WriteLine("Original Data: ");
Console.WriteLine(string.Join(" ", original.Elements));
SomeWeirdClass copy = original.Sort();
Console.WriteLine("Original Data after Sort and Assignment: ");
Console.WriteLine(string.Join(" ", original.Elements));
Console.WriteLine("Sorted Copy:");
Console.WriteLine(string.Join(" ", copy.Elements));
original.Sort();
Console.WriteLine("Original Data after Sort without Assignment: ");
Console.WriteLine(string.Join(" ", original.Elements));
}
The program outputs:
Original Data:
5 1 4 3 2
Original Data after Sort and Assignment:
5 1 4 3 2
Sorted Copy:
1 2 3 4 5
Original Data after Sort without Assignment:
1 2 3 4 5
The hack here is that sorting actually creates a temporary class which wraps the original. Unless that result is implicitly cast to the original type via assignment, the sorting effects will be applied to the original dataset. If assignment is made, the sorting is cancelled, and a copy is made for the new variable.
It is not possible in a reliable way. The compiler can optimize
MyClass exampleObject2 = exampleObject1.sort(); to exampleObject1.sort(); if exampleObject2 is not used.
To answer a slightly different question: you could return a Lazy<MyClass>. So you can do the sort only if the result is actually used.
Split the Copy and Sort methods into two distinct methods. If I want to sort a copy, I should be responsible for copying before I sort. For example:
var copy = myCollection.Copy();
copy.Sort();
The goal should be making it clear what your function is doing to any calling code. Different behavior based on usage is only going to lead to bugs, at least in the C# world.
my problem is as follows:
Im building a console application which asks the user for the numbers of objects it should create and 4 variables that have to be assigned for every object.
The new objects name should contain a counting number starting from 1.
How would you solve this?
Im thinking about a class but im unsure about how to create the objects in runtime from userinput. Is a loop the best way to go?
What kind of class, struct, list, array .... would you recommend. The variables in the object are always the same type but i need to name them properly so I can effectivly write methods to perform operations on them in a later phase of the program.
Im just learning the language and I would be very thankful for a advice on how to approach my problem.
If I understand your problem correctly:
class MyClass
{
public int ObjectNumber { get; set; }
public string SomeVariable { get; set; }
public string AnotherVariable { get; set; }
}
// You should use keyboard input value for this
int objectsToCreate = 10;
// Create an array to hold all your objects
MyClass[] myObjects = new MyClass[objectsToCreate];
for (int i = 0; i < objectsToCreate; i++)
{
// Instantiate a new object, set it's number and
// some other properties
myObjects[i] = new MyClass()
{
ObjectNumber = i + 1,
SomeVariable = "SomeValue",
AnotherVariable = "AnotherValue"
};
}
This doesn't quite do what you described. Add in keyboard input and stuff :) Most of this code needs to be in some kind of Main method to actually run, etc.
In this case, I've chosen a class to hold your 4 variables. I have only implemented 3 though, and I've implemented them as properties, rather than fields. I'm not sure this is necessary for your assignment, but it is generally a good habit to not have publically accessible fields, and I don't want to be the one to teach you bad habits. See auto-implemented properties.
You mentioned a struct, which would be an option as well, depending on what you want to store in it. Generally though, a class would be a safer bet.
A loop would indeed be the way to go to initialize your objects. In this case, a for loop is most practical. It starts counting at 0, because we're putting the objects in an array, and array indexes in C# always start at 0. This means you have to use i + 1 to assign to the object number, or the objects would be numbered 0 - 9, just like their indexes in the array.
I'm initializing the objects using object initializer syntax, which is new in C# 3.0.
The old fashioned way would be to assign them one by one:
myObjects[i] = new MyClass();
myObjects[i].ObjectNumber = i + 1;
myObjects[i].SomeVariable = "SomeValue";
Alternatively, you could define a constructor for MyClass that takes 3 parameters.
One last thing: some people here posted answers which use a generic List (List<MyClass>) instead of an array. This will work fine, but in my example I chose to use the most basic form you could use. A List does not have a fixed size, unlike an array (notice how I initialized the array). Lists are great if you want to add more items later, or if you have no idea beforehand how many items you will need to store. However, in this case, we have the keyboard input, so we know exactly how many items we'll have. Thus: array. It will implicitly tell whoever is reading your code, that you do not intend to add more items later.
I hope this answered some questions, and raised some new ones. See just how deep the rabbit hole goes :P
Use a list or an array. List example:
int numberOfObjects = 3;
List<YourType> listOfObjects = new List<YourType>();
for(int i = 0 ; i < numberOfObjects ; i++ )
{
// Get input and create object ....
// Then add to your list
listOfObjects.Add(element);
}
Here, listOfObjects is a Generic list that can contain a variable number of objects of the type YourType. The list will automatically resize so it can hold the number of objects you add to it. Hope this helps.
If I understood what you are asking you could probably do something like this:
class Foo
{
private static int count;
public string name;
public Foo(...){
name = ++count + "";
}
}
I'm guessing what you're trying to do here, but this is a stab in the dark. The problem I'm having is dealing with the whole "the new objects name should contain a counting number starting from 1" thing. Anyway, here's my attempt:
public class UserInstantiatedClass
{
public int UserSetField1;
public int UserSetField2;
public int UserSetField3;
public int UserSetField4;
public string UserSpecifiedClassName;
}
public static class MyProgram
{
public static void Main(string [] args)
{
// gather user input, place into variables named
// numInstances, className, field1, field2, field3, field4
List<UserInstantiatedClass> instances = new List< UserInstantiatedClass>();
UserInstantiatedClass current = null;
for(int i=1; i<=numInstances; i++)
{
current = new UserInstantiatedClass();
current.UserSpecifiedClassName = className + i.ToString(); // adds the number 1, 2, 3, etc. to the class name specified
current.UserSetField1 = field1;
current.UserSetField2 = field2;
current.UserSetField3 = field3;
current.UserSetField4 = field4;
instances.Add(current);
}
// after this loop, the instances list contains the number of instances of the class UserInstantiatedClass specified by the numInstances variable.
}
}
I would like my default constructor to create & initialize all the objects shown in my code snippet. Then I would like my parameterized constructor to call the default constructor, thus creating and initializing those objects, that can then be used in the parameratized constructor without getting a NullReferenceException.
In this situation, I'm not really sure what the best (most efficient, less code, etc.) way to use constructors is. I'd prefer to use constructor chaining.
Again, I have a very elementary understanding of constructors, so if this is not possible, then please just tell me so, and tell me what you would do in this situation.
class Rectangle
{
public Line left { get; set; }
public Line top { get; set; }
public Line right { get; set; }
public Line bottom { get; set; }
public Rectangle() : this(new Line()) { }
public Rectangle(Line diagnonal)
{
left = new Line();
top = new Line();
right = new Line();
bottom = new Line();
Point beginningDiagonalPoint = new Point();
Point endingDiagonalPoint = new Point();
beginningDiagonalPoint = diagnonal.startPoint;
endingDiagonalPoint = diagnonal.endPoint;
int begXC = beginningDiagonalPoint.xCoord;
int begYC = beginningDiagonalPoint.yCoord;
int endXC = endingDiagonalPoint.xCoord;
int endYC = endingDiagonalPoint.yCoord;
Point rightSideEnd = new Point();
rightSideEnd.xCoord = endXC;
rightSideEnd.yCoord = begYC;
Point leftSideEnd = new Point();
leftSideEnd.xCoord = begXC;
leftSideEnd.yCoord = endYC;
// ----------- right side definitions -------------
right.startPoint = endingDiagonalPoint;
right.endPoint = rightSideEnd;
// ------------ left side definitions --------------
left.startPoint = beginningDiagonalPoint;
left.endPoint = leftSideEnd;
// ------------ top side definitions -------------
top.startPoint = leftSideEnd;
top.endPoint = endingDiagonalPoint;
// ------------ bottom side definitions -----------
bottom.startPoint = rightSideEnd;
bottom.endPoint = beginningDiagonalPoint;
}
}
I just added
: this()
after the parametrized constructor. It was a bit of guess, but it seems to work.
Usually when you chain constructors it's the other way around: the default constructor calls the more specific constructors with the default values. Say, you have a Point constructor that takes the x and y coordinates. Then you have the default Point constructor call the other one with x = 0 and y = 0. This way you only have to write the code to set the values once.
Here are some things you can improve in your code:
You initialize beginningDiagonalPoint and endingDiagonalPoint to new points and then you overwrite them with references to diagnonal.startPoint and diagnonal.endPoint. You are creating two new points and then discarding them. You don't need to create those new points.
You create new Points and new Lines with the default constructor and then manually set their fields. You could create a point constructor that receives the two coordinates and sets them, and a line constructor that receives the two end points and sets them. Your code would look like this:
Point rightSideEnd = new Point(endXC, begYC);
Point leftSideEnd = new Point(begXC, endYC);
right = new Line(endingDiagonalPoint, rightSideEnd);
left = new Line(beginningDiagonalPoint, leftSideEnd);
top = new Line(leftSideEnd, endingDiagonalPoint);
bottom = new Line(rightSideEnd, beginningDiagonalPoint);
Your paramaterised constructor already initialises all your properties. So, I think all you need to do is pass some sort of default into the paramaterised constructor from your default constructor.
You need to answer this question yourself: what is a default or empty Rectangle? I'm going to assume it's a zero sized one.
So, presuming a Line takes two points as parameters, I'd do this:
public Rectangle() : this(new Line(new Point(0,0), new Point(0,0))) { }
And in a less condensed format:
public Rectangle()
: this(
new Line(
new Point(0,0),
new Point(0,0)
)
)
{ }
Your example nearly does what you are asking for. The way you've done it, though, it's the default constructor that calls the paramaterized contructor, giving it a default parameter to work with. There's nothing wrong with doing it this way, it's just not what you said you were looking for.
Also, it's conventional for public properties to begin with capital letters (Left, Right, Top, Bottom instead of left, right, top, bottom). Notice that all the .NET library classes do it this way.