Correct syntax to initialize static array [duplicate] - c#

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
I have following code definig an array
public class PalphabetsDic
{
public static string[] PAlphCodes = new string[3] {
PAlphCodes[0] = "1593",
PAlphCodes[1] = "1604",
PAlphCodes[2] = "1740",
};
}
When I use this array
var text = PalphabetsDic.PAlphCodes[1]
Gives error:
The type initializer for 'Dota2RTL.PalphabetsDic' threw an exception.
---> System.NullReferenceException: Object reference not set to an instance of an object.
Please can someone help me on this?
Note that What is a NullReferenceException, and how do I fix it? covers arrays, but PAlphCodes = new string[3] should be setting it up to be not null.

When initializing the way you are you don't need to index the values:
public static string[] PAlphCodes = new string[] {
"1593",
"1604",
"1740",
};

To expand upon what Kennedy answered -- you can also use
public static string[] PAlphCodes = { "1593", "1604", "1740" };
The reference manual has a listing of all the possible ways -- but the one Kennedy suggested -- and this method -- are probably the most common.
https://msdn.microsoft.com/en-us/library/aa287601(v=vs.71).aspx

Indeed you've used strnage syntax to initialize array as pointed out in other answers and something like static string[] PAlphCodes = new []{"1","2","3"}; would fix the problem.
On why this actually compiles (which is somewhat surprising for most people):
You can use static fields to initialize other static fields, but surprisingly you can also refer to static field inside initialization if the field itself. So there is no compile time error.
It fails at run-time first with NullReferenceException because initialization of the array is not completed by the time it is used for first time - so PAlphCodes is null while array is created. But since this is part of class level initialization (as it is static filed) this exception also stops class instance creation and you get "The type initializer ...." wrapping NullReferenceException .
Note that in most cases such construct would not even compile. I.e.
using it in non-static field of local variable fails at compile time with
A field initializer cannot reference the non-static field, method, or property ...
public class PalphabetsDic
{
public string[] PAlphCodes = new string[3] {
PAlphCodes[0] = "1593", // error here and other lines
PAlphCodes[1] = "1604",
PAlphCodes[2] = "1740",
};
}

Related

What does "initializing an instance of a class" mean?

After reading Meanings of declaring, instantiating, initializing and assigning an object it talks about what initializing a variable means. But it doesn't explain what "initializing" an instance of a class means.
public class Test
{
public static void Main()
{
Person person1 = new Person();
}
}
public class Person
{
// body
}
What does it mean to initialize an instance of a class?
Yeah, I don't like the "initialize" of the linked answer so much either, because it really only talks about giving a value to a single variable and doesn't really draw any distinctions between instantiation and assignment (the same lines of code are found in all of them) so for me it's a bit vague. We do have more specific processes (especially these days of modern c# syntax) when we talk about initialization
Initialize usually means "to give a created instance some initial values". Your class Person has nothing to initialize, so you could say that just by making it anew(instantiating) you've also done all the initialization possible and it's ready for use
Let's have something we can set values on
public class Person{
public string Name {get;set;}
public string Address {get;set;}
public Person(string name){
if(name == null) throw new ArgumentNullException(nameof(name));
Name = name;
}
}
Initializing as part of construction:
p = new Person("John");
Constructors force us to supply values and are used to ensure a developer gives a class the minimum set of data it needs to work.. a Person must have a name. Address is optional. We have created a person with the name initialized to John
Initializing post construction
You can give an instance additional (optional) values after you construct it, either like
p = new Person("Bill");
p.Address = "1 Microsoft Way";
Or
p = new Person("Bill"){
Address = "1 Microsoft Way"
}
Which is a syntactic sugar the compiler unrolls to something like the first. We refer to everything in the { } brackets of the second example as "an object initializer". An important distinction here though is that the first form (p.Address=...) is not considered to be initialization by the compiler. If you made the address property like:
public string Address {get;init;}
Then it can only be set in a constructor or in an object initializer, which is the latter form above. The p.Address=... form would result in a compiler error if the property were declared with init
Props set just after construction are part of the initialization process (as an English/linguistic thing) though I wouldn't call it init if it was any further down the line, such as
p = new Person("Sam");
string addr = Console.ReadLine();
p.Address = addr; //not initialization
You might find cases where people talk about initialization in the sense for "the first time a variable or property is given a value" but that's also more a linguistic/English thing than a c# thing
The compiler knows how to perform other initialization, so we also call things like this "an initializer":
string[] x = new string[] {"a","b","c"};
The process of giving the array those 3 values is initialization, and the compiler will even take the type of the first argument and use it to make the array type, so an array can be type declared and ignited from the data:
var x = new[] {"a","b","c"};

Why left-hand side of an assignment must be a variable property or indexer? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
private ArrayList arr = new ArrayList();
private ArrayList Test()
{
return arr;
}
private void WhyMustVariable()
{
Test() = new ArrayList(); // error: left-hand side of an assignment must be a variable property or indexer
}
Why cannot i do this Test() = ...;
Thanks.
When writing test().xyz = xxx you first execute test which onbiously returns some instance of ArrayList (btw. you should consider to use List<T> instead nowadays, which is strongly typed and thus safes you from casting every element in your list to its actual type). Now You can of course do what you want with that instance, e.g. call another method or set any of its properties. This would be equivalent to doing this:
var val = test();
val.MyMember = 3;
However when using test() = ... you´re assigning a new value to the return-value of the method, which clearly makes no sense.
I suppose what you want instead is provide some parameter to your method. To do so your method also should expect one:
ArrayList test(int myInt)
{
// do something with myInt
}
And call it like this:
var list = test(3);
An assignment must have a place to store the value assigned, and this has to be a variable or a property (indexer is a special kind of property).
A property assignment is silently converted into a method call.
Test() = ...
where Test() returns something cannot be used as the target of an assignment because what is returned is a value, not a variable (nor a property).

Using a reference value as parameter, with or without "ref"? [duplicate]

This question already has answers here:
Why use the 'ref' keyword when passing an object?
(10 answers)
Closed 7 years ago.
I came accross two Solutions(both work):
public List<Label> foo1(ref ISomeInterface[] all)
or
public List<Label> foo2(ISomeInterface[] all)
Is there a diffrerence, does it matter which of them I take ? Interface is a reference value and will give the parameter as reference anyway and "ref" will also get the reference...I think I can dismiss "ref" ... I wonder why the compiler does not give me an error...
Is there a diffrerence?
Yes, there is. Everything in C# is passed by value. When you pass a reference type by ref, you pass the actual reference pointer rather then a copy. That way, if you pass a reference type by ref and set it to a new reference via the new keyword, you'll alter the reference.
An example:
public static void Main(string[] args)
{
ISomeInterface[] somes = new[] { new SomeConcreteType() }
Foo(somes);
Console.WriteLine(somes.Length) // Will print 1
Foo(ref somes);
Console.WriteLine(somes.Length) // Will print 0
}
public List<Label> Foo(ref ISomeInterface[] all)
{
all = new ISomeInterface[0];
}
public List<Label> Foo(ISomeInterface[] all)
{
all = new ISomeInterface[0];
}
In first case you replace "global" (out of method) parameter all. In second case you will replace local copy of all parameter.
public List<Label> foo1(ref ISomeInterface[] all)
{
all = new ISomeInterface[0]; //you will get empty array outside method
}
public List<Label> foo1(ISomeInterface[] all)
{
all = new ISomeInterface[0]; //you will get empty array only inside method
}
It depends on what you want to do with the array.
If you want to modify the value in the foo1 method and use those modifications outside of the foo1 method, you may want to use the ref type version
If you just want to use the returned List<Label> you should use the option without ref.

Does C# pass a List<T> to a method by reference or as a copy? [duplicate]

This question already has answers here:
Are arrays or lists passed by default by reference in c#?
(4 answers)
Closed 8 years ago.
Taking my first steps in C# world from C/C++, so a bit hazy in details. Classes, as far as I understood, are passed by reference by default, but what about eg. List<string> like in:
void DoStuff(List<string> strs)
{
//do stuff with the list of strings
}
and elsewhere
List<string> sl = new List<string>();
//next fill list in a loop etc. and then do stuff with it:
DoStuff(sl);
Is sl in this case passed by reference or is a copy made so that I'd need to redefine the worker function like void DoStuff(ref List<string> strs) to actually act on sl itself and not a copy?
It's passed by reference. List<T> is a class, and all class instances are passed by reference.
The behaviour is always the same: Passing by copying. In case the parameter is an object, the reference to the object is copied, so in fact you are working on the same object/list/whatever.
In addition to other answers it is very important to understand the behavior of ref
Here is some sample code for demonstration purpose
static void Main(string[] args)
{
List<string> lstStr = new List<string>();
lstStr.Add("First");
lstStr.Add("Second");
Alter(lstStr);
//Alter(ref lstStr);
Console.WriteLine("---From Main---");
foreach (string s in lstStr)
{
Console.WriteLine(s);
}
Alter2(ref lstStr);
Console.WriteLine("---From Main after passed by ref---");
foreach (string s in lstStr)
{
Console.WriteLine(s);
}
Console.ReadKey();
}
static void Alter(List<string> lstStr2)
{
lstStr2.Add("Third");
Console.WriteLine("----From Alter----");
foreach (string s in lstStr2)
{
Console.WriteLine(s);
}
lstStr2 = new List<string>();
lstStr2.Add("Something new");
Console.WriteLine("----From Alter - after the local var is assigned somthing else----");
foreach (string s in lstStr2)
{
Console.WriteLine(s);
}
}
static void Alter2(ref List<string> lstStr2)
{
lstStr2 = new List<string>();
lstStr2.Add("Something new from alter 2");
Console.WriteLine("----From Alter2 - after the local var is assigned new list----");
foreach (string s in lstStr2)
{
Console.WriteLine(s);
}
}
//----From Alter----
//First
//Second
//Third
//----From Alter - after the local var is assigned somthing else----
// Something new
// ---From Main---
// First
// Second
// Third
// ----From Alter2 - after the local var is assigned new list----
// Something new from alter 2
// ---From Main after passed by ref---
// Something new from alter 2
The underlying thing always is: value types are passed by value, and reference types are "passed by reference" (quoted because the value of the reference is actually passed by value, but most people ignore that for the sake of brevity).
The easiest way to reconcile the ref keyword against references is: reference types have their reference passed by value. This has the effect, in the standard case, of simply passing the reference to the list (and not the entire list) to the method.
The ref keyword, when used on a reference type, semantically passes a reference to the reference (I really struggle not to say "pointer to a pointer").
If your method were to re-assign the ref argument to a new object, the caller would also see this new assignment. Whereas without the ref keyword, the method would simply be re-assign their own local copy of the reference value and the caller would still have a reference to their original object.
The above explanation is shamelessly taken from Jon Skeet's article on the topic:
This difference is absolutely crucial to understanding parameter
passing in C#, and is why I believe it is highly confusing to say that
objects are passed by reference by default instead of the correct
statement that object references are passed by value by default.
The ref keyword is only needed if you intend to re-assign the argument and have that visible to the caller. In most cases you will find that it isn't needed. Your DoStuff can be re-written to remove it and still pass a reference to the list by value successfully:
void DoSomething(List<string> strs)
{
strs.Add("Hello");
}
The ref keyword in your method is redundant if you want to modify the original list: List<T> is a reference type (class in C#) and so will be passed to the method by reference; therefore the method will manipulate the original list.
When passing a Value Type, it will create a copy of the value itself.
When passing a Reference Type, it will create a copy of the reference.
Read more about Value and Reference Types in C#.
The list is passed by reference. What that means is actually that the strs variable inside the method refers to the same list as the sl variable outside the method.
If you would use ref, you can actually reassign the the sl variable inside the method.
strs = new List<string>()
would make sl point to the new list.
Since you're coming from C/C++: ref could be considered a 'safe pointer'. It is similar to using &strs
Its by reference. Not necesary to include "ref".
Best regards.

A field initializer cannot reference the non-static field, method, or property

Ok so I have the code below, technically all it does is read the db.txt file line by line and then its suppose to split the line 0 into an array called password.
private string[] lines = System.IO.File.ReadAllLines(#"U:\Final Projects\Bank\ATM\db.txt");
private string[] password = lines[0].Split(' ');
but I get the error:
A field initializer cannot reference the non-static field, method, or property
Have a think about what the above means and how you want to populate those variables. You'd need to first construct the class they are a member of, and then hope the lines of code get executed in the order you want them to, and that they don't throw an exception.
The compiler is effectively telling you this isn't the right way to do things.
A better way is to simply write a function to do what you want:
private string[] PasswordLines(){
string[] lines = System.IO.File.ReadAllLines(#"U:\Final Projects\Bank\ATM\db.txt");
return lines[0].Split(" ");
}
You can then call this from anywhere you wanted to; for example:
public class MyClass()
{
private string[] Lines
{
get { return PasswordLines(); }
}
private string[] PasswordLines(){
string[] lines = System.IO.File.ReadAllLines(#"U:\Final Projects\Bank\ATM\db.txt");
return lines[0].Split(" ");
}
}
C# does not guarantees any specific order of execution when it comes to filed initialization.
For instance these two lines of code will produce undefined results:
private int a = b + 1;
private int b = a + 1;
in theory, the two possible outcomes are a=1,b=2 or a=2,b=1, but in fact it's even worst. We don't even know if a and b are initialized to their default values yet (0 in case of int), so it can be anything (just like a reference to uninitialized object).
To avoid this impossible-to-solve scenario, the compiler demands that all field initializations will be "run-time constants" (return the same value every time, whenever they are executed and independent of any other non "run-time constant" variables).
Just use the constructor when you initialize compound fields and life will be sweet again.
Exactly what is says! Those are (instance) field initializers, and cannot reference each other. Move the code to the constructor instead, or make them method variables instead of fields.
The error is self explanatory.
you can't do this because lines and password both are field variables and you can't assign
one of them value to other(if it's a static then you can).
i hope you are using this code inside a class so until unless an object is not create their no such real existence of these field variables so you can't assign them to each other.

Categories

Resources