Suppose I have a class like this:
class Array{
int[] values;
}
Now suppose I have a class that stores a lot of Arrays:
class ArrayOfArrays{
Array[] arrays;
}
Suppose, for some reason, I want to get the last Array of arrays and put in a variable (for better readability). In C, I would do like Array last = &ArrayOfArraysObject.arrays[lastIndex]. As I won't modify it, for better performance, I don't need to copy the whole array, just a reference do the job.
Can I have this kind of behaviour in C# ? (without using function calls, I don't want to create a function just to use the keyword ref, it looks like overkill)
You could create a public property that returns the last element of arrays.
class ArrayOfArrays
{
Array[] arrays;
public Array LastOfArrays { get { return arrays.Last(); } }
}
Test it:
var aoa = new ArrayOfArrays();
// Initialize and enter data here
//When you want to use the last item:
var last = aoa.LastOfArrays;
last.values[0] = 333;
Now, aoa.arrays[LastElement].values[0] would also be 333. So you essentially do keep the reference here, and does not copy the entire array.
Confirmation:
Arrays already use references in C#. You don't have to do anything special, and you get the behavior you want:
int[][] foo = new int[][] { new int[] {1,2,3}, new int[]{4,5,6}, new int[]{7,8,9} };
var bar = foo[2];
foo[2][2] = 0; // make a change **after** assigning to bar
Console.WriteLine(bar[2]); // outputs "0" -- bar knows about the change
bar[1] = 6; // same thing, but in reverse
Console.WriteLine(foo[2][1]); // outputs "6" -- foo knows about the change
In the example above, foo[2] and bar are references to the same array in memory. bar was not just a copy.
Related
I have an array of List types:
List<object>[] vector = new List<object>[3];
The first List contains strings:
// Get word lists together, remove duplicates
var words = tableA.ToList().Union(tableB.ToList());
// Sort words
words = words.OrderBy(s => s, StringComparer.CurrentCultureIgnoreCase);
// Add words to the vector first slot
vector[0] = words.ToList<object>();
Now, I want to add ints to the second and third lists, but I get an error here:
vector[1].Add(tableA.GetValue(keyword));
vector[2].Add(tableB.GetValue(keyword));
GetValue() returns an int. But when I add these ints to the vector Lists it throws error:
ERROR Caught: Object reference not set to an instance of an object.
How should I add the ints to the List? Or is there some other data structure I should use instead for the vector? I feel there is some trivial cast I'm missing but I haven't been able find a solution.
I'm not an expert in C#, but i think i understand.
When you write :
List<object> vector = new List<object>[3];
you create a table of List with a size of 3.
You can put something into each slot of this array, but each "slot" still refers to no instance after this first line of code.
When you write
vector[0] = words.ToList<object>();
You put somehting into the first slot of vector list. But [1] and [2] are still empty. And
vector[1]
refers to a reference not set to an instance of an object. In short terms, it refers to nothing.
You must initialize each vector index value before add value. Thanks
When writing var a = new List<object> you´re only declaring that a is a list holding some (in your case three) items. However you don´t determine what stands in those three elements. You´d have to out some values into every single item, before you can anything with it (e.g. call any method).
You´re allready putting a list into the first item, however the elements on index one and two remain null causing a NullReferenceException when calling a method like the following:
vector[1].Add(...);
So you should initialize the value at index oe and two before:
vector[1] = new List<int>();
vector[2] = new List<int>();
But still you can´t do much with the list, because it is of type object, so you´d have to cast every element to the actual type:
((List<int>)vector[1]).Add(myInt);
Anyway I doubt storing three completely different lists within one single list alltogether is a good idea. Maybe you should define a class with the three lists as members instead:
class MyClass
{
public List<string> Words { get; set; }
public List<int> NumbersA { get; set; }
public List<int> NumbersB { get; set; }
}
Let's say a program like this:
class MyClass
{
public int Numbers;
public char Letters;
}
class Program
{
static void Main()
{
var mc = new MyClass[5];
for (var i = 0; i < 5; i++)
{
mc[i].Numbers = i + 1;
mc[i].Letters = (char) (i + 65);
}
}
}
Now, let's suppose an 'X' method that requires ALL the numbers contained in the object mc, in a separate array, that's sent as a parameter.
My first idea is a for, a new integers array, and copy one by one onto its respective position. But, what if the MyClass gets different, now it has strings and floats, and I wanna pull out the strings, now the for has to be completely redefined in its inside part to create the needed array for another 'X' method.
I know of cases where Linq helps a lot, for example, generics for Sum, Average, Count and another numeric functions, and of course, it's combination with lambda expressions.
I'm wondering if something similar exists to make the above arrays of MyClass (and anothers of course) in a faster-generic way?
If you want to use LINQ, you can do something like the following:
int [] numbers = mc.Select<MyClass, int>(m => mc.Number).ToArray();
To make it more generic than that, it gets a bit more complicated, and you may need reflection, or dynamic objects. A simple example with reflection would be:
private TValue[] ExtractFields<TClass, TValue>(TClass[] classObjs, string fieldName)
{
FieldInfo fInfo = typeof(TClass).GetField(fieldName, BindingFlags.Public | BindingFlags.Instance);
if (fInfo != null && fInfo.FieldType.Equals(typeof(TValue)))
return classObjs.Select<TClass, TValue>(c => (TValue)fInfo.GetValue(c)).ToArray();
else
throw new NotSupportedException("Unidentified field, or different field type");
}
And then just call it like:
int [] fields = ExtractField<MyClass, int>(mc, "Number");
If you are using C# 4.0, then you may use dynamic
class MyClass
{
public dynamic Numbers;
public char Letters;
}
EDIT: based on comments
I am not sure if this is what you want:
int[] arr = mc.Select(a => a.Numbers).ToArray<int>();
or without casting
int[] arr = mc.Select(a => a.Numbers).ToArray();
Why not just use Dictionary<int, char>, or if the data type is unknown then simply Dictionary<object, object>
If your goal is to generate a new array which is detached from the original array, but contains data copied from it, the most generic thing you could do would be to define a method like:
T my_array[]; // The array which holds the real things
U[] CopyAsConvertedArray<U>(Func<T,U> ConversionMethod);
That would allow one to generate a new array which extracts items from the original using any desired method.
I am planning to rewrite my Python Tile Engine in C#. It uses a list of all the game objects and renders them on the screen. My problem is that unlike in Python where you can add almost anything to an array (e.g x = ["jj" , 1, 2.3, 'G', foo]) you can add only one type of objects
in a C# array (int[] x = {1,2,3};) . Are there any dynamic arrays (similar to the ArrayList() class) or something which allows you to pack different types into a single array? because all the game objects are individual classes.
Very simple—create an array of Object class and assign anything to the array.
Object[] ArrayOfObjects = new Object[] {1,"3"}
you can use an object array. strings, int, bool, and classes are all considered objects, but do realize that each object doesn't preserve what it once was, so you need to know that an object is actually a string, or a certain class. Then you can just cast the object into that class/data type.
Example:
List<object> stuff = new List<object>();
stuff.add("test");
stuff.add(35);
Console.WriteLine((string)stuff[0]);
Console.WriteLine((int)stuff[1]);
Though, C# is a strongly typed language, so I would recommend you embrace the language's differences. Maybe you should look at how you can refactor your engine to use strong typing, or look into other means to share the different classes, etc. I personally love the way C# does this, saves me a lot of time from having to worry about data types, etc. because C# will throw any casting (changing one data type to another) errors I have in my code before runtime.
Also, encase you didn't know, xna is C#'s game framework (didn't have it as a tag, so I assume you aren't using it).
You can write an abstract base class called GameObject, and make all gameObject Inherit it.
Edit:
public abstract class GameObject
{
public GameObject();
}
public class TileStuff : GameObject
{
public TileStuff()
{
}
}
public class MoreTileStuff : GameObject
{
public MoreTileStuff()
{
}
}
public class Game
{
static void Main(string[] args)
{
GameObject[] arr = new GameObject[2];
arr[0] = new TileStuff();
arr[1] = new MoreTileStuff();
}
}
C# has an ArrayList that allows you to mix types within an array, or you can use an object array, object[]:
var sr = new ArrayList() { 1, 2, "foo", 3.0 };
var sr2 = new object[] { 1, 2, "foo", 3.0 };
In c# we use an object[] array to store different types of data in each element location.
object[] array1 = new object[5];
//
// - Put an empty object in the object array.
// - Put various object types in the array.
// - Put string literal in the array.
// - Put an integer constant in the array.
// - Put the null literal in the array.
//
array1[0] = new object();
array1[1] = new StringBuilder("Initialized");
array1[2] = "String literal";
array1[3] = 3;
array1[4] = null;
You can use object[] (an object array), but it would be more flexible to use List<object>. It satisfies your requirement that any kind of object can be added to it, and like an array, it can be accessed through a numeric index.
The advantage of using a List is you don't need to know how items it will hold when you create it. It can grow and shrink dynamically. Also, it has a richer API for manipulating the items it contains.
Here is how you can do it
Use List<object> (as everything is derived from object in C#):
var list = new List<object>();
list.Add(123);
list.Add("Hello World");
Also dynamic might work for you (and your python background)
var list = new List<dynamic>();
list.Add(123);
list.Add(new
{
Name = "Lorem Ipsum"
});
If you wan't to use dynamic you really need to know what you're doing. Please read this MSDN article before you start.
But do you need it?
C# is a strongly-typed and very solid programming language. It is very flexible and great for building apps using object-oriented and functional paradigms. What you want to do may be acceptable for python, but looks pretty bad on C#. My recommendation is: use object oriented programming and try to build model for your problem. Never mix types together like you tried. One list is for a single data-type. Would you like to describe your problem in depth so that we can suggest you a better solution?
In C# 4 and later you can also use dynamic type.
dynamic[] inputArray = new dynamic[] { 0, 1, 2, "as", 0.2, 4, "t" };
Official docu
You can mix specific types doing the following:
(string, int)[] Cats = { ("Tom", 20), ("Fluffy", 30), ("Harry", 40), ("Fur Ball", 40) };
foreach (var cat in Cats)
{
Console.WriteLine(string.Join(", ", cat));
}
You have to declare your array with the datatype object:
object[] myArray = { };
myArray[0] = false;
myArray[1] = 1;
myArray[2] = "test";
You can use an array of object class and all it possible to add different types of object in array.
object[] array = new object[3];
array[0] = 1;
array[1] = "string";
array[3] = 183.54;
I have a struct in C# and I define and array list of my struct based on my code that I express here. I add items in my array list, but I need to delete a few rows from my list too. Could you help me how can I delete item or items from my struct array list:
public struct SwitchList
{
public int m_Value1, m_Value2;
public int mValue1
{
get { return m_Value1; }
set {m_Value1 = value; }
}
public int mValue2
{
get { return m_Value2; }
set {m_Value2 = value; }
}
}
//Define an array list of struct
SwitchList[] mSwitch = new SwitchList[10];
mSwitch[0].mValue1=1;
mSwitch[0].mValue2=2;
mSwitch[1].mValue1=3;
mSwitch[1].mValue2=4;
mSwitch[2].mValue1=5;
mSwitch[2].mValue2=6;
Now how can I delete one of my items, for example item 1.
Thank you.
Arrays are fixed length data structures.
You will need to create a new array, sized one less than the original and copy all items to it except the one you want to delete and start using the new array instead of the original.
Why not use a List<T> instead? It is a dynamic structure that lets you add and remove items.
You will need to move elements around and resize the array (which is expensive), since there is some complexity there you going to want to hide it in class that just presents the collection without exposing the implementation details of how its stored. Fortunately Microsoft has already provided a class that does just this called List<T> which along with a few other collection types in System.Collections.Generic namespace meet most common collection needs.
as a side note, you should use auto-properties instead of the trivial property style that you ha
That's not possible, because an array is a fixed size block of elements. Because structs are values types and not reference types, you also can't just set the element zo null. One option would be to create a new smaller array and to copy your remaining values to the new array. But the better approach would be to use a List in my opinion.
If you really, really want to use arrays and move things around, here are some examples of how to do it:
{
// Remove first element from mSwitch using a for loop.
var newSwitch = new SwitchList[mSwitch.Length - 1];
for (int i = 1; i < mSwitch.Length; i++)
newSwitch[i - 1] = mSwitch[i];
mSwitch = newSwitch;
}
{
// Remove first element from mSwitch using Array.Copy.
var newSwitch = new SwitchList[mSwitch.Length - 1];
Array.Copy(mSwitch, 1, newSwitch, 0, mSwitch.Length - 1);
mSwitch = newSwitch;
}
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.
}
}