In the following code block, why do I need to declare myData in the class, then initialize myData = new string[size] in the constructor? Why is it illegal to code private string[] myData = new string[size] ?
That is, why do I need to do:
class IntIndexer
{
private string[] myData;
public IntIndexer(int size)
{
myData = new string[size];
for (int i = 0; i < size; i++)
{
myData[i] = "empty";
}
}
}
Instead of
class IntIndexer
{
private string[] myData = new string[size];
public IntIndexer(int size)
{
for (int i = 0; i < size; i++)
{
myData[i] = "empty";
}
}
}
Because the variable "size" only exists in the constructor.
Because you do not know what size will be, or even if it exists outside the constructor.
Inline initialisers run as part of all constructors in the class. Adding another constructor without size would break your class if this were implemented, a confusing state of affairs.
Also even if the compiler were made smart enough to check for all this it would be a confusing abuse of scope. What if there were a constant field called size somewhere else in the class?
All these are reasons to not attempt to allow this sort of thing and there are precious little benefits to it so why bother.
Because size is only known to the constructor at run-time - not compile-time. If you wanted to size myData to a constant size - i.e. known at compile-time, then you could do it in the declaration:
private string[] myData = new string[1000];
or
private const int DATA_SIZE = 1000;
private string[] myData = new string[DATA_SIZE];
Because size is a parameter of the constructor and only exists within the scope of the constructor.
The issue here is one of scope. You can't reference size, a parameter of the constructor, outside the constructor because it isn't defined outside the constructor. This will give you a compile error. If the variable were defined in the object, it would be perfectly legal, but you'd be dependent on the order of initialization as to whether you would get the effect you intended. If the initializer for the variable were run before the initializer for the array, then it might work. IMO, you're better off doing the initialization in the constructor because that way you define the order of execution and know what will happen, when.
Because you don't know the size until the constructor is called. The following field definition is fine:
private string[] myData = new string[100];
you cannot do that for one reason: How would the compiler know how big size is at compile time?
if you want to initialise an array with a runtime-variable size, you must initialise it within a runtime method when the variable has a value!
Because if you try to do in this way
class IntIndexer
{
private string[] myData = new string[size];
public IntIndexer(int size)
{
for (int i = 0; i < size; i++)
{
myData[i] = "empty";
}
}
}
you will get compilation error
The name 'size' does not exist in the current context.
beacuse at this point
private string[] myData = new string[size];
size is not yet declared.
And if you will write in this way from where you will get the value of size as your objective i think will be to make it flexible and let the instance do that for you that's why your objective can be done by this
class IntIndexer
{
private string[] myData;
public IntIndexer(int size)
{
myData = new string[size];
for (int i = 0; i < size; i++)
{
myData[i] = "empty";
}
}
}
ie you will be setting that size like this
IntIndexer instance = new IntIndexer(100);
Related
I've been learning C#, and I'm trying to understand lambdas. In this sample below, it prints out 10 ten times.
class Program
{
delegate void Action();
static void Main(string[] args)
{
List<Action> actions = new List<Action>();
for (int i = 0; i < 10; ++i )
actions.Add(()=>Console.WriteLine(i));
foreach (Action a in actions)
a();
}
}
Obviously, the generated class behind the lambda is storing a reference or pointer to the int i variable, and is assigning a new value to the same reference every time the loop iterates. Is there a way to force the lamda to grab a copy instead, like the C++0x syntax
[&](){ ... } // Capture by reference
vs.
[=](){ ... } // Capture copies
What the compiler is doing is pulling your lambda and any variables captured by the lambda into a compiler generated nested class.
After compilation your example looks a lot like this:
class Program
{
delegate void Action();
static void Main(string[] args)
{
List<Action> actions = new List<Action>();
DisplayClass1 displayClass1 = new DisplayClass1();
for (displayClass1.i = 0; displayClass1.i < 10; ++displayClass1.i )
actions.Add(new Action(displayClass1.Lambda));
foreach (Action a in actions)
a();
}
class DisplayClass1
{
int i;
void Lambda()
{
Console.WriteLine(i);
}
}
}
By making a copy within the for loop, the compiler generates new objects in each iteration, like so:
for (int i = 0; i < 10; ++i)
{
DisplayClass1 displayClass1 = new DisplayClass1();
displayClass1.i = i;
actions.Add(new Action(displayClass1.Lambda));
}
The only solution I've been able to find is to make a local copy first:
for (int i = 0; i < 10; ++i)
{
int copy = i;
actions.Add(() => Console.WriteLine(copy));
}
But I'm having trouble understanding why putting a copy inside the for-loop is any different than having the lambda capture i.
The only solution is to make a local copy and reference that within the lambda. All variables in C# (and VB.Net) when accessed in a closure will have reference semantics vs. copy/value semantics. There is no way to change this behavior in either language.
Note: It doesn't actually compile as a reference. The compiler hoists the variable into a closure class and redirects accesses of "i" into a field "i" inside the given closure class. It's often easier to think of it as reference semantics though.
Remember that lambda expressions are really only syntactic sugar for anonymous methods.
That being said, what you are really looking for is how anonymous methods use local variables in a parent scope.
Here's a link describing this. http://www.codeproject.com/KB/cs/InsideAnonymousMethods.aspx#4
Given a class:
class clsPerson { public int x, y; }
Is there some way to create an array of these classes with each element initialized to a (default) constructed instance, without doing it manually in a for loop like:
clsPerson[] objArr = new clsPerson[1000];
for (int i = 0; i < 1000; ++i)
objArr[i] = new clsPerson();
Can I shorten the declaration and instantiation of an array of N objects?
The constructor must be run for every item in the array in this scenario. Whether or not you use a loop, collection initializers or a helper method every element in the array must be visited.
If you're just looking for a handy syntax though you could use the following
public static T[] CreateArray<T>(int count) where T : new() {
var array = new T[count];
for (var i = 0; i < count; i++) {
array[i] = new T();
}
return array;
}
clsPerson[] objArary = CreateArray<clsPerson>(1000);
You must invoke the constructor for each item. There is no way to allocate an array and invoke your class constructors on the items without constructing each item.
You could shorten it (a tiny bit) from a loop using:
clsPerson[] objArr = Enumerable.Range(0, 1000).Select(i => new clsPerson()).ToArray();
Personally, I'd still allocate the array and loop through it (and/or move it into a helper routine), though, as it's very clear and still fairly simple:
clsPerson[] objArr = new clsPerson[1000];
for (int i=0;i<1000;++i)
clsPerson[i] = new clsPerson();
If it would make sense to do so, you could change class clsPerson to struct Person. structs always have a default value.
I have a task where I need to have two values for one key in Dictionary.
Solution found in web is to make new class with two fields and use it's objects as values.
But how can I assign value to my CustomClassObjects from Dictionary's for loop?
Here is the code:
Dictionary<char, Huffmans> HuffmanDictionary = new Dictionary<char, Huffmans>();
Program.text = File.ReadAllText(Program.sourcetext);
char character;
for (int i = 0; i < Program.text.Length; i++)
{
counter++;
character = Convert.ToChar(Program.text[i]);
if (HuffmanDictionary.ContainsKey(character))
HuffmanDictionary[character].probability++;
else
HuffmanDictionary.Add(character, 1);// here is the problem, obviously program can't assign value directly to class...
}
public class Huffmans
{
public int code = 0;
public double probability = 0;
}
Basically, I need to assign only "probability" values on this step. Should I call constructor for "Huffmans " on each iteration?
Big thanks for any help, Alex
You need to instantiate your class before adding the value:
HuffmanDictionary.Add(character, 1);
Should be:
HuffmanDictionary.Add(character, new Huffmans{ code = 1 });
Alternatively you can create a constructor for your class:
public class Huffmans
{
public Huffmans(int _code)
{
code = _code;
}
public int code = 0;
public double probability = 0;
}
then you can do:
HuffmanDictionary.Add(character, new Huffmans(1));
EDIT:
Some more clarification:
HuffmanDictionary.Add(character, 1);
fails because you are passing a type int into the dictionary but it is expecting the type Huffmans. Our dictionary is : Dictionary<char,Huffmans>()
HuffmanDictionary.Add(character, new Huffmans{ code = 1 });
works because now we are creating a new object of type Huffmans and we are setting the code value to 1.
Not sure if I understood your comment correctly, but effectively we are doing the same as:
var newHuffmans = new Huffmans{ code = 1 };
HuffmanDictionary.Add(character, newHuffmans);
But rather than writing out all that code and creating a named variable with our class, we skip this and pass it directly into the dictionary.
I'm learning about Indexers and stumble across the explanation and example of the tutorial I'm reading.
It says:
"An indexer allows an object to be indexed such as an array. When you define an indexer for a class, this class behaves similar to a virtual array. You can then access the instance of this class using the array access operator ([ ])"
What I understand with this paragraph is that you can access an instance of that class using the array access operatos.
But what I really dont understand of this explanation is the following:
"Declaration of behavior of an indexer is to some extent similar to a property. similar to the properties, you use get and set accessors for defining an indexer. However, properties return or set a specific data member, whereas indexers returns or sets a particular value from the object instance. In other words, it breaks the instance data into smaller parts and indexes each part, gets or sets each part".
I dont get the "It breaks the instance data into smaller parts and indexes each part"
After this it gives an example of Indexer:
using System;
namespace IndexerApplication
{
class IndexedNames
{
private string[] namelist = new string[size];
static public int size = 10;
public IndexedNames()
{
for (int i = 0; i < size; i++)
namelist[i] = "N. A.";
}
public string this[int index]
{
get
{
string tmp;
if( index >= 0 && index <= size-1 )
{
tmp = namelist[index];
}
else
{
tmp = "";
}
return ( tmp );
}
set
{
if( index >= 0 && index <= size-1 )
{
namelist[index] = value;
}
}
}
static void Main(string[] args)
{
IndexedNames names = new IndexedNames();
names[0] = "Zara";
names[1] = "Riz";
names[2] = "Nuha";
names[3] = "Asif";
names[4] = "Davinder";
names[5] = "Sunil";
names[6] = "Rubic";
for ( int i = 0; i < IndexedNames.size; i++ )
{
Console.WriteLine(names[i]);
}
Console.ReadKey();
}
}
}
Before that paragraph I thought Indexers where a form to index and instance of that class as an array, but that "smaller parts" I really dont understand.
It's really just giving an example of the use of an indexer. Returning an element from the array is, in a way, returning part of the array.
But it needn't be an array. For example, String has an indexer which returns the character at that position, e.g. "test"[0] returns the character in position zero, which is 't'.
Other objects may have other indexers which do other things. For example a DataTable DataRowCollection has an indexer which returns rows by number, and which has an indexer which returns columns by name:
myDataTable.Rows[12]["ID"].Value
CardDetails is a Structure.
public static void ParceIntricaciesJabber(ref CardDetails[] WhichArray)
{
WhichArray[0].ID = 50;
WhichArray[0].Type = "None";
}
In calling:
ParceIntricaciesJabber(ref OpponentCards);
After I call the function though, another Array called PlayerCards is affected in the exact same way as OpponentCards - despite being declared as two different arrays. They have the same number of elements and the same data Type, and that's it.
This probably should be obvious but i'm not seeing it. The code works in VB.NET. What am I doing wrong?
EDIT: Initialization Code:
public static class Module1{
public static CardDetails[] PlayerCards = new CardDetails[100];
public static CardDetails[] OpponentCards = new CardDetails[100];
}
And also when navigating to the Form
for (int n = 1; n <= 100; n++)
{
Module1.PlayerCards[n] = new CardDetails();
Module1.OpponentCards[n] = new CardDetails();
}
My guess is that you are sharing the reference to the arrays. Even though it is structs inside the array, the array itself is a reference type. You will need to post your array instantiation code to verify one way or the other though