Alternate name for object instances stored in array, C# - c#

I have 2 object instances of same type. (To be precise this is Unity3D's AudioSource) I need to apply some action like initializing, destroying, etc to both, so I think storing them in an array would be a good idea so I can iterate.
AudioSource[] audioSources = new AudioSource[2];
With this I can foreach on the array and write initializing code and other common tasks only once.
But these two instances serves different purpose, say, the first is an AudioSource for BGM and the second is for SFX. This way the code will be more readable and I can still iterate over two instances by using the array.
So I think I should give an alternate names for each instance like bgmSource and sfxSource. I'd like to ask that is this the correct approach?
AudioSource bgmSource = audioSources[0];
AudioSource sfxSource = audioSources[1];

Another solution is using a Dictionary, its not very suitable for such small arrays
but it can help you distinct between objects without using second variable to store reference
to the one in the array.
For example:
Dictionary< string, AudioSource > audioSources;
audioSources = new Dictionary<string, AudioSource>
{
"BGM_SOURCE", new AudioSource(),
"SFX_SOURCE", new AudioSource()
};
Then you can also use enum for keeping track of dictionary keys instead of using string/constant values:
// Enum declaration
enum AudioSourceNames
{
BGM_SOURCE,
SFX_SOURCE
}
// Called before first update
public void Start()
{
// Dictionary declaration
Dictionary< int, AudioSource > audioSources;
audioSources = new Dictionary< int, AudioSource >
{
( int )BGM_SOURCE, new AudioSource(),
( int )SFX_SOURCE, new AudioSource()
};
// Accessing the dictionary
audioSources[ ( int )AudioSourceNames.BGM_SOURCE ].Play();
}
BTW: You can use the enumarator technique with array, this way you won't have to remember each AudioSource index in the array

From my point of view your solution seem good.
initializing code and other common tasks only once
The code for these things is hopefully in AudioSource, isn't it?

Well, it's legal. It's just a matter of preference/design. I would say that you could put them in a Dictionary of some sort. So you can properly label them through a key. That way you won't need to remember that [0] is bgmSource and [1] is sfxSource.

Related

C# getting array with a string name?

So here's a hypothetical. From someone fairly new to the whole C# and Unity thing:
Suppose for a moment that I have a series of string[] arrays. All of which have similar naming convention. For example:
public string[] UndeadEntities =
{
// stuff
};
public string[] DemonEntities =
{
// stuff
};
Now suppose I want to call one of them at random, I have another list that contains the names of all of those arrays and I return it at random.
My problem is that I grab the name from the array and it's a string, not something I can use. So my question is this:
is there any way for me to use this string and use it to call the above mentioned arrays.
Something like this is what I'm up to but unsure where to go from here and I really would like to avoid making a massive series of If Else statements just for that.
public string[] EnemiesType = { // list of all the other arrays }
public string enemiesTypeGeneratedArrayName = "";
public void GenerateEncounterGroup()
{
enemiesTypeGeneratedArrayName = EnemiesType[Random.Range(0, 12)];
}
Can I nest arrays inside of other arrays? Is there another alternative?
I'm not sure if it is possible at all but if it is, I'll take any pointers as to where to go from there. Thanks.
There are several solutions to your specific problem, an easy one is using Dictionaries:
A Dictionary is a data structure wher you have a key (usually a string) and a value (whatever type you may want to store).
What you can do is at start, initialized a Dictionary were each key is your enemy type, and the value it store is your array, something like:
Dictionary<string, string[]> enemyArrays= new Dictionary<string, string[]>();
.
void Start()
{
enemyArrays["typeA"] = myArrayA;
enemyArrays["typeB"] = myArrayB;
}
Then when you need to get that array, just:
enemiesTypeGeneratedArrayName = EnemiesType[Random.Range(0, 12)];
string[] myRandomArray =enemyArrays[enemiesTypeGeneratedArrayName];
string randomEnemy = myRandomArray[index];
Here you can read more about Dictionary class if you want.
There are other ways to do it, but I think this one is pretty easy to implement in the code you already made, and Dicionaries are cool haha.
I hope is clear:)

Why do I get an error when List<object>.Add(int)

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; }
}

Check a value exist in array in unity 3d

I have two script.
Script1
Script2
In Script1 i declared a arraylist it contains value 2, 4, 6, etc...
public static ArrayList aArray= new ArrayList();
function update(){
if(bool1)
{
aArray.Add(i);
}
}
I have to check a value 5 exist in arraylist from Script2.
if value exists i have to get its key.
How to get it?
First, i would recommand using a generic List<T> instead of the non-generic ArrayList, which enables you to specify the type of objects that go into that list (for better type safety).
Also, declaring a variable readonly prevents you from accidently overwriting it, which is often the case with Lists (after all, you can always just Clear them):
public static readonly List<int> items = new List<int>();
Now to answer your actual question, if you want to check if a value exists in the list, you can use the method Contains.
To check if the value does not exist, just put an ! in front of the expression:
if (!Script1.items.Contains(i)) {
// This will only execute if the list does not contain i.
items.Add(i);
}
Try using Contains. This code will detect if you have already the value in the ArrayList and will stop code from adding it a second time.
public static ArrayList aArray= new ArrayList();
function update()
{
if(aArray.Contains(i)==false)
{
aArray.Add(i);
}
}
If you want to remove a value it is just as easy as aArray.Remove(i)
if I understood correctly, Script1 is in your camera, and Script2 is in a Character. For the sake of this example we'll call them MainCamera and Character respectively.
Now, unless I understood wrong, you're trying to access an Array in Script1 from Script2. While the other answers are very much correct, unity3D has a bit of a workaround needed to access it.
Anyway, within Script2 use this:
if(GameObject.Find("MainCamera").GetComponent<Script1>().aArray.Contains(5))
{
//Do your code here
}

Arrays of data classes in C#

I've been messing around with this for ages and I'm not getting any closer.
My current version is as below. The comments are what I think I'm doing.
The semantic is basically an index number (like a house number) and a list of attributes in an array. Then create an array 'street'. I want to be able to update the values of all elements in the current scope. The class is defined as high as possible so as to make the scope global. My ossified 'C' brain doesn't really understand things like lists and IEnumerable so I haven't tried to go that route. The code parser in the editor makes a bit of a mess of this - sorry.
public class house
{
// Ok, looking at this from the world of 'C' and thinking 'struct' like,
// I put my variables here.
public int my_id;
public long [] pl_id;
public house()
{
// I try to initialise the starting values, so I can carry out some tests later.
my_id = 0;
pl_id = new long[10] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
}
}
// I attempt to inform the compiler that I will be wanting an array of the house objects
// and call that array 'new_house'. Again, the code editor isn't keen.
house [] new_house;
private void button1_Click(object sender, EventArgs e)
{
// In the programs main routine (not *main*!), I then try to get the
// array 'new_house' populated with initialised 'house' objects
for (int idx = 0; idx < 10; idx++)
{
new_house[idx] = new house();
}
// And at some point in the future I wish to set or update the values arbitrarily. eg:
new_house[7].my_id = 123;
new_house[7].pl_id = 345678;
// any combination of attributes and id numbers is possible, so I use zero simply to see if they have been set, with -1 indicating failure / an absence of data-
}
}
Right. As I say, I've tried a lot of different ways to do this, and the main problem I am getting is that I never seem to correctly initialise the array 'new_house' and get null exceptions thrown when I try to assign anything. I can't believe something that seems so intuitively simple can be so hard to code, so where have I got it wrong (and I fully accept that there could be more than one conceptual or coding error in the above).
Comments on appropriateness of approach, and help with coding alike, gratefully accepted.
You need to instantiate the array before initializing items of it:
house[] new_house = new house[10];
Replace 10 with desired number of items.
In case you don't know the number, use List:
List<house> new_house = new List<house>()
Then you can dynamically add items using new_house.Add(item) and access them in foreach loop or through index new_house[i]
The first obvious problem with your code is that your constructor doesn't have the same name as the class. It should be this:
public house()
{
// ...
}
A second point is you don't need the constructor at all here:
public int my_id = 0; // The "= 0" is actually not needed here either.
public long[] pl_id = new long[10];
I would also suggest that you don't use arrays for things like houses on a street because house numbers won't necessarily be sequential. You can have gaps and even multiple houses with the "numbers" 5A and 5B. A dictionary might be a better choice.
IDictionary<string, house> houses = new Dictionary<string, house>();
If you really want to have sequential numbering you might want to consider a List<house> instead of an array so that it can be easily extended if new houses are built.
Finally I'd advise using PascalCase for classes. It will make your code much easier to read if you use the same standards as the rest of the .NET framework.
Change public game()
to public house()
Your constructor has to have the same name as the class.
A couple things:
new_house is never initialized. You can't use it until you've initialized it.
pl_id is an array, but you attempt to store a long in it (345678) -- you could change it to new int[] { 345678}.
You've got a method, game(), in the class house which looks and acts like a constructor. You would have to name it house() if it is meant to be a constructor.
not public game()
right: public house()
Always the constructor has to have the same name as the class.
Use List<T> for those collections. Try not to say you don't understand something because you are 'c' addicted. Try to say yourself you want to try something new and search for a good solution
namespace Myprog
{
// I attempt to inform the compiler that I will be wanting an array of the house objects
// and call that array 'new_house'
List<house> houselist = new List<house>();
private void button1_Click(object sender, EventArgs e)
{
// In the programs main routine (not *main*!), I then try to get the
// array 'new_house' populated with initialised 'house' objects
for (int idx = 0; idx < 10; idx++)
{
houselist.add(new house());
}
// And at some point in the future I wish to set or update the values arbitrarily. eg:
houselist[7].my_id = 123;
// any combination of attributes and id numbers is possible, so I use zero simply to see if they have been set, with -1 indicating failure / an absence of data-
}
}
}

How to reset a Dictionary

If I declared a dictionary like this:
private static Dictionary<string, object> aDict = new Dictionary<string, object>();
And now I want to use it at another place. How do I reset it?
aDict = new Dictionary<string, object>(); // like this?
aDict = null; // or like this?
or other reset styles?
You can simply use the Clear method, it will remove all keys and values, then you can reuse it without having to create new instances:
aDict.Clear();
Try this
aDict.Clear();
aDict.Clear(); will work.
aDict.Clear(); is the only way to go since you don't want to change the reference and keep the same object available at another place
As everybody has pretty much answered that .Clear() method provided on the Dictionary class should be the way to go here (can't agree more).
Just to make it clear (for newbies of course ;)) that why not the other approaches, like creating a new instance every time we need to refresh the dictionary
aDict = new Dictionary<string, object>(); // like this?
because even though this way works, it is not a memory efficient approach as this creates a new instance and leaves behind the old instance(s) of the dictionary waiting for GC (garbage collector) to dispose it (as it is no longer referred). So you would agree on not consuming extra memory when you don't need to :)
and
aDict = null; // or like this?
because this leaves your instance set to null and next time as the OP wanted to use it as a dict, OP has to create another instance (yes, you got it right not memory efficient)
and also this won't be a better programming style here as someone might end up doing .ContainsKey() (or any operation on the dictionary for that matter)on the aDict variable and cause a nullPointerException if aDict is still pointing to a null object.
Hope this explanation helps!! Thanks for reading!
Running a decompile of the Clear method in Resharper on a Dictionary object shows this:
/// <summary>Removes all keys and values from the <see cref="T:System.Collections.Generic.Dictionary`2" />.</summary>
[__DynamicallyInvokable]
public void Clear()
{
if (this.count <= 0)
return;
for (int index = 0; index < this.buckets.Length; ++index)
this.buckets[index] = -1;
Array.Clear((Array) this.entries, 0, this.count);
this.freeList = -1;
this.count = 0;
this.freeCount = 0;
++this.version;
}
The dictionary contains an integer array of buckets and other control variables that are either set to -1 or 0 to effectively clear the keys and values from the dictionary object. It is pretty many variables representing a valid state of the Dictionary as we can see in the .NET source code. Interesting.

Categories

Resources