C# accessing class instance from method - c#

Seems like I'm struggling with a pretty basic problem right now, but I just can't find a good solution..
I have this code-snippet here:
public Form1()
{
InitializeComponent();
BaseCharacterClass myChar = new BaseCharacterClass();
}
public void setLabels()
{
lbName.Text = myChar.CharacterName;
lbHealthPoints.Text = (myChar.CharHPcurrent + "/" + myChar.CharHPmax);
lbMagicPoints.Text = (myChar.CharHPcurrent + "/" + myChar.CharMPmax);
lbClass.Text = myChar.CharacterClass;
}
It says "myChar" does not exist in the current scope..
How do I fix that?

You just need to declare myChar outside of the constructor. You can define it on the class and then assign it on the constructor:
BaseCharacterClass myChar;
public Form1()
{
InitializeComponent();
myChar = new BaseCharacterClass();
}
public void setLabels()
{
lbName.Text = myChar.CharacterName;
lbHealthPoints.Text = (myChar.CharHPcurrent + "/" + myChar.CharHPmax);
lbMagicPoints.Text = (myChar.CharHPcurrent + "/" + myChar.CharMPmax);
lbClass.Text = myChar.CharacterClass;
}

You didnt declare the variable as a class variable, only a local one. In c# the format is:
MyNamespace
{
class MyClassName
{
//class wide variables go here
int myVariable; //class wide variable
public MyClassName() //this is the constructor
{
myVariable = 1; // assigns value to the class wide variable
}
private MyMethod()
{
int myTempVariable = 4; // method bound variable, only useable inside this method
myVariable = 3 + myTempVariable; //myVariable is accessible to whole class, so can be manipulated
}
}
}
And so on. Your current constructor only declares a local variable within the constructor, not a class wide one

Related

Unity: Cannot modify / add values to an array in System.Serializable

I have a System.Serializable class
[System.Serializable]
public class _answersData
{
public string word;
public string wordmeaning;
public string wordmeaning2;
public GameObject result;
}
I then have a monobehaviour class where an array of _answerData class is declared
public class gamePlay : MonoBehaviour
{
public _answersData[] answersData;
}
I am then trying to add data to _answerData array from another script using below method
public class challengeScript: MonoBehaviour
{
void Start()
{
gameplayScript = gameObject.GetComponent<gamePlay>();
populate();
}
void populate()
{
answersCount = int.Parse(snapshot.Child("Answers").Child("Count").Value.ToString());
gameplayScript.answersData = new _answersData[answersCount];
for (int i = 0; i < answersCount; i++)
{
string positionNode = "Answer" + (i + 1).ToString();
string _word = snapshot.Child("Answers").Child(positionNode).Child("Word").Value.ToString();
gameplayScript.answersData[i].word = _word;
}
}
}
but I am getting NullReferenceException at 'gameplayScript.answersData[i].word = _word' line
Here's the error:
NullReferenceException: Object reference not set to an instance of an object
Can someone guide what I am doing wrong here?
Just because it is [Serializable] doesn't mean the elements are automatically created once you create the array. By default all reference type elements will still be null.
Only within Unity the Inspector itself automatically creates instances of [Serializable] types and initializes the array itself.
In code you have to actually create your element instances yourself like e.g.
var answerData = new _answerData();
answerData.word = _word;
gameplayScript.answersData[i] = answerData;

instantiate subclass by string na C#

I have a Class and a Sub Clas
namespace MyCode
{
public class Class1
{
int a = 1;
int b = 2;
public class SubClass1
{
int a = 1;
int b = 2;
}
}
}
Now I need to instantiate each class by string name. I can do this from the class, but not for the subclass.
This works:
var myObj = Activator.CreateInstance(Type.GetType("MyCode." + "Class1"));
But this, dinĀ“t work:
var myObj = Activator.CreateInstance(Type.GetType("MyCode." + "Class1.SubClass1"));
What I need to do for the second option?
Whenever you don't know what a name should be you can see the name by checking typeof(MyCode.Class1.SubClass1).FullName.
When you have a subclass you use the + sign.
var myObj = Activator.CreateInstance(Type.GetType("MyCode." + "Class1+SubClass1"));
var myObj = Activator.CreateInstance(Type.GetType("MyCode.Class1+SubClass1"));
Its + when dealing with nested types, not .

modify public string with default value in C#

I have an string like "0000000"
and declared it in a class
public class Days_string
{
private string days= "0000000";
public string Days
{
get
{
return days;
}
set
{
days = value;
}
}
}
and I tried to change the string by clicking on 7 buttons
like this:
Days_string daystr = new Days_string();
var aStringBuilder = new StringBuilder(daystr.Days);
aStringBuilder.Remove(5, 1);
aStringBuilder.Insert(5, "1");
daystr.Days = aStringBuilder.ToString();
the output is 0000010
but it changed to 0000000 when I call it again
whats should i do?
Use static variable and static properties instead.and access the properties using className.properties name
public class Days_string
{
private static string days = "0000000";
public static string Days
{
get
{
return days;
}
set
{
days = value;
}
}
}
Even though the code is strange, but to solve your problem, you have at least two options:
Use an static variable :
private static string days = "0000000";
Or, create a global Days_string instance inside your form. By now, you are creating a new Days_string instance behind each button!

Accessing generic object in generic list in C#

I am relatively new to C# and I would like to create a list of generic objects.
Here is how I try to do it:
I create a base class:
public class BaseClass
{
}
And I inherit a generic class from the base class:
public class GenericClass<T> : BaseClass where T: struct
{
public T data;
public GenericClass(T value)
{
data = value;
}
public T doSomething()
{
return (T)(data * (dynamic)0.826f);
}
}
Then I can create a list of base class:
List<BaseClass> ListOfGenericClasses = new List<BaseClass>();
And I can add instances of the inherited geneic class:
ListOfGenericClasses.Add(new GenericClass<int>(100));
ListOfGenericClasses.Add(new GenericClass<byte>(101));
ListOfGenericClasses.Add(new GenericClass<float>(10.1f));
ListOfGenericClasses.Add(new GenericClass<double>(100.10));
ListOfGenericClasses.Add(new GenericClass<ulong>(9999999999));
ListOfGenericClasses.Add(new GenericClass<long>(-9999999999));
ListOfGenericClasses.Add(new GenericClass<uint>(62389));
ListOfGenericClasses.Add(new GenericClass<sbyte>(-103));
I also can invoke each objects method:
string s = "";
s += ((GenericClass<int>)(ListOfGenericClasses[0])).doSomething() + " # ";
s += ((GenericClass<byte>)(ListOfGenericClasses[1])).doSomething() + " # ";
s += ((GenericClass<float>)(ListOfGenericClasses[2])).doSomething() + " # ";
s += ((GenericClass<double>)(ListOfGenericClasses[3])).doSomething() + " # ";
s += ((GenericClass<ulong>)(ListOfGenericClasses[4])).doSomething() + " # ";
s += ((GenericClass<long>)(ListOfGenericClasses[5])).doSomething() + " # ";
s += ((GenericClass<uint>)(ListOfGenericClasses[6])).doSomething() + " # ";
s += ((GenericClass<sbyte>)(ListOfGenericClasses[7])).doSomething();
MessageBox.Show(s);
And here comes the question: how do I get the value of each instance in the list generally?
I try to do something like this:
string s = "";
for (int i = 0; i < ListOfGenericClasses.Count; i++)
{
s += ((GenericClass<ListOfGenericClasses[i].GetType().GetGenericArguments()[0]>)(ListOfGenericClasses[i])).dosdoSomething() + " # ";
}
MessageBox.Show(s);
I have the following error message: "Using the generic type 'GenericClass requires 1 type argument'"
EDIT: sorry guys I could have been more precize when asking my question: my point was not to use the return value to build a string it was just for seeing the result on screen
Any help is much apreciated,
Thanks in advance
I'd approach it in a slightly different way:
public class BaseClass
{
public virtual string DoSomethingToString() { throw new NotImplementedException(); }
}
Then you'd implement your derived class as follows:
public class GenericClass<T> : BaseClass where T: struct
{
public T data;
public GenericClass(T value)
{
data = value;
}
public T DoSomething()
{
return (T)(data * (dynamic)0.826f);
}
public override string DoSomethingToString()
{
return DoSomething().ToString();
}
}
Now you can iterate List<BaseClass> and directly call each element's DoSomethingToString() method.
Does this do what you want?
string s = "";
for (int i = 0; i < ListOfGenericClasses.Count; i++)
{
Type type = ListOfGenericClasses[i].GetType();
dynamic d = Convert.ChangeType(ListOfGenericClasses[i], type);
s += d.doSomething() + " # ";
}
It looks like you are trying to implement a union type. I am sure there must be better ways than this.
Should you use Generics? I re-wrote your app and solved the problem by removing Generics
public class GenericClass : BaseClass
{
public object data;
public GenericClass(object value)
{
this.data = value;
}
public object doSomething()
{
return (object)(this.data * (dynamic)0.826f);
}
}
Then I did it:
for (var i = 0; i < ListOfGenericClasses.Count; i++)
{
s += ListOfGenericClasses[i].doSomething() + " # ";
}
You would need to use reflection to get the type and then from that get the method which you can then invoke:
string s = "";
for (int i = 0; i < ListOfGenericClasses.Count; i++)
{
s += ListOfGenericClasses[i].GetType()
.GetMethod("doSomething")
.Invoke(ListOfGenericClasses[i], null);
}
However, I would recommend you take the approach as suggested by #corak in the comments and by #InBetween in their answer and create a virtual method in BaseClass and override it in GenericClass.
First use stringBuilder to concat strings, you can cast your object to dynamic to invoke the method you need dynamically:
var stringbuilder = new StringBuilder();
foreach (var l in ListOfGenericClasses)
{
var st = (l as dynamic).doSomething() + " # ";
stringbuilder.Append(st);
}
MessageBox.Show(stringbuilder.ToString());

Inconsistent accessibility

Hi I am a little new in programming in C#, and I am a little stuck. I have tried searching this site, but I have not been successful on finding an answer to my question. I have also tried changing my private to a public but that did not work.
Here is the error message I am getting:
Error 2 Inconsistent accessibility: parameter type 'exam2.location' is
less accessible than method
'exam2.Form1.MoveToANewLocation(exam2.location)'
Here is part of my code:
public Form1()
{
IntializeComponent();
CreateObject();
MoveToANewLocation(livingRoom);
}
private void MoveToANewLocation(location newLocation)
{
currentLocation = newLocation;
comboBox1.Items.Clear();
for (int i = 0; i < currentLocation.Exits.Length; i++)
{
comboBox1.Items.Add(currentLocation.Exits[i].Name);
comboBox1.SelectedIndex = 0;
}
textBox1.Text = currentLocation.Description;
if (currentLocation is IHasExteriorDoor)
{
GoThroughTheDoor.Visible = true;
}
else
{
GoThroughTheDoor.Visible = false;
}
}
abstract class location
{
public location(string name)
{
this.name = name;
}
public location[] Exits;
private string name;
public string Name
{
get { return name; }
}
public virtual string Description
{
get {
string description = "You're standing in the" + name +
". You see exits to the following places: ";
for (int i = 0; i < Exits.Length; i++)
{
description += " " + Exits[i].Name;
if (i != Exits.Length - 1)
description += ",";
}
description += ",";
return description;
}
}
}
Make location class public if it's not public already
You need to declare your class this way:
public abstract class location
{
...
}
As an aside, general code style has classes starting with a capital letter (ie. Location).
C# defaults the accessibility to internal, so having public methods inside the class will cause this error (like your constructor, properties, and virtual method). A good rule of thumb is to always declare classes public unless you know for sure you want everything in them to be internal or lower.
See MSDN for more information on access modifiers.

Categories