Having simple difficulties with encapsulation - c#

I'm new to programming and I have this script that I'm making, it makes a function that reads XML files based on your input, I've just ran into this issue though where I cannot access the variable named "XMLtext", it's public, can someone tell me what I'm doing wrong and explain it, I've tried various things.
using UnityEngine;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Linq;
using System.Collections;
public class Data : MonoBehaviour {
public TextAsset XMLtext;
void Main () {
}
public static string XMLread (params string[] no) {
var XMLfile = XDocument.Parse ();
var a = Data.XMLfile.Element ("data");
for (int i = 0; no[i] == null; i++) {
}
}
}

The problem is that your class Data, which owns the XMLtext field is an instance class. Your method XMLread is static, meaning it is shared across all instances of Data. To solve your problem either make XMLText static or make XMlread an instance method by removing the static keyword.

The problem is that your XMLtext field belongs to an instance of Data, while your XMLread method is static, so it belongs to the class Data. You probably just want to remove the static from XMLread, so that you're always in an instance of Data.

Related

Method not finding public list instantiated in the same class C#

I have instantiated a list. C# cannot find the list from within the same class.
I have added a PNG so you can see the intellisense and code highlighting. Along with the code. I note that I may not be adding to the list correctly, but that is not what I am worried about for the moment. What i'm having trouble with is the Update() function not highlighting the type in the arguments and TurnsLog list not being found from within the update function. It could be a syntax error with brackets or a semi-colon basic stuff, but I cannot spot what is wrong with it. Also it is instantiated in another class.
Source for Copy pasta.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace DumbDnD
{
public class Log
{
public void Initialize()
{
public List<GameplayState> TurnsLog = new List<GameplayState>();
}
public void Update(GameplaySate state)
{
TurnsLog.Add(GameplayState state);
}
}
I think you meant the list to be a member variable. As it is, you've declared it as a local variable within the Initialize method.
public class Log
{
public List<GameplayState> TurnsLog = new List<GameplayState>();
public void Update(GameplaySate state)
{
TurnsLog.Add(GameplayState state);
}
}
See also control variable scope and logic using code blocks in c#

Is there a way I can access the local variables of a method in a different script by using Reflection to get the method using a string?

I'm using the latest recommended version of Unity and I'm trying to access an array of strings localized in a method in a different script. I want to be able to access the method by using the GetMethod function in the System.Reflection library. There aren't any compiler errors in my script but whenever I try to test the game, Unity freezes. This is what I have so far:
preMaps = GetComponent<PreMaps>();
MethodInfo Method = preMaps.GetType().GetMethod(mapName);
Method.Invoke(preMaps, null);
foreach (LocalVariableInfo variable in Method.GetMethodBody().LocalVariables)
{
print(variable);
}
I simply put a print line to test if I was getting any variables out of the method and I previously declared the preMaps variable as a PreMaps class at the beginning of the script. The mapName variable is a string that matches the name of a method in the other script (previously declared and initialized). Is there anything that I'm missing? I've tested it without these lines and Unity doesn't freeze.
using UnityEngine;
public class PreMaps : MonoBehaviour
{
public class MapName
{
public readonly static string[] map = {
"p,250,110,50,184,10",
"start,10",
"n,0,0,0,100",
"fin"
};
}
}
This is all that's in the other script I'm trying to access.
PreMaps.MapName is a CLASS (Type), not a Method!
And PreMaps.MapName.map is a FIELD within that class, not a LocalVariable!
Anyway I see no need for / sense in using Reflection at all!
All your types and their fields are public anyway so as far as I can tell there is absolutely nothing that hinders you from simply doing
foreach (var mapValue in PreMaps.MapName.map)
{
Debug.Log(mapValue);
}

What is the difference between these using statements of interop in c# [duplicate]

Where or when would one would use namespace aliasing like
using someOtherName = System.Timers.Timer;
It seems to me that it would just add more confusion to understanding the language.
That is a type alias, not a namespace alias; it is useful to disambiguate - for example, against:
using WinformTimer = System.Windows.Forms.Timer;
using ThreadingTimer = System.Threading.Timer;
(ps: thanks for the choice of Timer ;-p)
Otherwise, if you use both System.Windows.Forms.Timer and System.Timers.Timer in the same file you'd have to keep giving the full names (since Timer could be confusing).
It also plays a part with extern aliases for using types with the same fully-qualified type name from different assemblies - rare, but useful to be supported.
Actually, I can see another use: when you want quick access to a type, but don't want to use a regular using because you can't import some conflicting extension methods... a bit convoluted, but... here's an example...
namespace RealCode {
//using Foo; // can't use this - it breaks DoSomething
using Handy = Foo.Handy;
using Bar;
static class Program {
static void Main() {
Handy h = new Handy(); // prove available
string test = "abc";
test.DoSomething(); // prove available
}
}
}
namespace Foo {
static class TypeOne {
public static void DoSomething(this string value) { }
}
class Handy {}
}
namespace Bar {
static class TypeTwo {
public static void DoSomething(this string value) { }
}
}
I use it when I've got multiple namespaces with conflicting sub namespaces and/or object names you could just do something like [as an example]:
using src = Namespace1.Subspace.DataAccessObjects;
using dst = Namespace2.Subspace.DataAccessObjects;
...
src.DataObject source = new src.DataObject();
dst.DataObject destination = new dst.DataObject();
Which would otherwise have to be written:
Namespace1.Subspace.DataAccessObjects.DataObject source =
new Namespace1.Subspace.DataAccessObjects.DataObject();
Namespace2.Subspace.DataAccessObjects.DataObject dstination =
new Namespace2.Subspace.DataAccessObjects.DataObject();
It saves a ton of typing and can be used to make code a lot easier to read.
In addition to the examples mentioned, type aliases (rather than namespace aliases) can be handy when repeatedly referring to generic types:
Dictionary<string, SomeClassWithALongName> foo = new Dictionary<string, SomeClassWithALongName>();
private void DoStuff(Dictionary<string, SomeClassWithALongName> dict) {}
Versus:
using FooDict = Dictionary<string, SomeClassWithALongName>;
FooDict foo = new FooDict();
private void DoStuff(FooDict dict) {}
Brevity.
There are fringe benefits to provide clarity between namespaces which share type names, but essentially it's just sugar.
I always use it in situations like this
using Utility = MyBaseNamespace.MySubNamsepace.Utility;
where Utility would otherwise have a different context (like MyBaseNamespace.MySubNamespace.MySubSubNamespace.Utility), but I expect/prefer Utility to always point to that one particular class.
It is very useful when you have multiple classes with the same name in multiple included namespaces. For example...
namespace Something.From.SomeCompanyA {
public class Foo {
/* ... */
}
}
namespace CompanyB.Makes.ThisOne {
public class Foo {
/* ... */
}
}
You can use aliases to make the compiler happy and to make things more clear for you and others on your team:
using CompanyA = Something.From.CompanyA;
using CompanyB = CompanyB.Makes.ThisOne;
/* ... */
CompanyA.Foo f = new CompanyA.Foo();
CompanyB.Foo x = new CompanyB.Foo();
We have defined namespace aliases for all of our namespaces. This makes it very easy to see where a class comes from, e.g:
using System.Web.WebControls;
// lots of other using statements
// contains the domain model for project X
using dom = Company.ProjectX.DomainModel;
// contains common web functionality
using web = Company.Web;
// etc.
and
// User from the domain model
dom.User user = new dom.User();
// Data transfer object
dto.User user = new dto.User();
// a global helper class
utl.SomeHelper.StaticMethod();
// a hyperlink with custom functionality
// (as opposed to System.Web.Controls.HyperLink)
web.HyperLink link = new web.HyperLink();
We have defined some guidelines how the aliases must be named and everyone is using them.
I find the aliases very useful in unit testing. When you are writing unit tests, it is a common practice to declare the subject to test as
MyClass myClassUT;
being myClassUT the subject Under Test. But what if you want to write unit tests for a static class with static methods? Then you can create an alias like this:
using MyStaticClassUT = Namespace.MyStaticClass;
Then you can write your unit tests like this:
public void Test()
{
var actual = MyStaticClassUT.Method();
var expected = ...
}
and you never loose sight of what the subject under test is.
In one way it is really handy while coding in Visual Studio.
Use-case: Let's say I've to use only few classes e.g. SqlConnection from a namespace System.Data. In normal course I'll import the System.Data.SqlClient namespace at the top of the *.cs file as shown below:
using System.Data;
Now look at my intellisense. It is heavily proliferated with whole lot of classes to choose from while typing in code editor. I'm not going to use whole bunch of classes at all:
So I would rather use an alias at the top of my *.cs file and get a clear intellisense view:
using SqlDataCon = System.Data.SqlClient.SqlConnection
Now look at my intellisense view. It is super-clear and super-clean.
One reason I know; It lets you use shorter names when you have name collisions from imported namespaces.
Example:
If you declared using System.Windows.Forms; and using System.Windows.Input; in the same file when you go to access ModifierKeys you might find that the name ModifierKeys is in both the System.Windows.Forms.Control and System.Windows.Input namespaces.
So by declaring using Input = System.Windows.Input; you can then get System.Windows.Input.ModifierKeys via Input.ModifierKeys.
I'm not a C# buff but aliasing namespace seems like "best practise" to me. That way you know what you're getting and still don't have to type too much more.
You can use them to modify a code very easily.
For example:
#if USE_DOUBLES
using BNumber = System.Double;
#else
using BNumber = System.Single;
#endif
public void BNumber DoStuff(BNumber n) {
// ...
}
public void BNumber DoStuff2(BNumber n) {
// ...
}
public void BNumber DoStuff3(BNumber n) {
// ...
}
By the simple change in of the directive you can decide if your whole code works in float or double.

Thought I understood static classes

Trying to construct a helper class that will return an arraylist, but I'm getting the following error, having to do with the xml document I need to create:
Util.oDocument': cannot declare instance members in a static class
I think I understand why you wouldn't want to create a new xmldoc object each time this method gets called, but I need that doc in there for the functionality. How should I be approaching this?
using System;
using System.Collections;
using System.Xml;
public static class Util
{
public static ArrayList multipleArtistList(string artistName)
{
XmlDocument oDocument = new XmlDocument();
string uri = "http://api.leoslyrics.com/api_search.php?auth=duane&artist=" + artistName;
oDocument.Load(uri);
XmlNodeList results = oDocument.GetElementsByTagName("name");
ArrayList artistList = new ArrayList();
for (int i = 0; i < results.Count; i++)
{
if (!artistList.Contains(results[i].InnerText))
{
artistList.Add(results[i].InnerText);
}
}
return artistList;
}
}
This error here:
Util.oDocument: cannot declare instance members in a static class
means that you've declared oDocument outside of the method.
There's nothing wrong with the code you posted, in fact the error and the code contradict each other.
Make sure that oDocument is declared inside the method. If you want to declare it as a field, make sure to give it the static modifier, like so:
public static class Util
{
static XmlDocument oDocument;
/* code */
}

C# namespace alias - what's the point?

Where or when would one would use namespace aliasing like
using someOtherName = System.Timers.Timer;
It seems to me that it would just add more confusion to understanding the language.
That is a type alias, not a namespace alias; it is useful to disambiguate - for example, against:
using WinformTimer = System.Windows.Forms.Timer;
using ThreadingTimer = System.Threading.Timer;
(ps: thanks for the choice of Timer ;-p)
Otherwise, if you use both System.Windows.Forms.Timer and System.Timers.Timer in the same file you'd have to keep giving the full names (since Timer could be confusing).
It also plays a part with extern aliases for using types with the same fully-qualified type name from different assemblies - rare, but useful to be supported.
Actually, I can see another use: when you want quick access to a type, but don't want to use a regular using because you can't import some conflicting extension methods... a bit convoluted, but... here's an example...
namespace RealCode {
//using Foo; // can't use this - it breaks DoSomething
using Handy = Foo.Handy;
using Bar;
static class Program {
static void Main() {
Handy h = new Handy(); // prove available
string test = "abc";
test.DoSomething(); // prove available
}
}
}
namespace Foo {
static class TypeOne {
public static void DoSomething(this string value) { }
}
class Handy {}
}
namespace Bar {
static class TypeTwo {
public static void DoSomething(this string value) { }
}
}
I use it when I've got multiple namespaces with conflicting sub namespaces and/or object names you could just do something like [as an example]:
using src = Namespace1.Subspace.DataAccessObjects;
using dst = Namespace2.Subspace.DataAccessObjects;
...
src.DataObject source = new src.DataObject();
dst.DataObject destination = new dst.DataObject();
Which would otherwise have to be written:
Namespace1.Subspace.DataAccessObjects.DataObject source =
new Namespace1.Subspace.DataAccessObjects.DataObject();
Namespace2.Subspace.DataAccessObjects.DataObject dstination =
new Namespace2.Subspace.DataAccessObjects.DataObject();
It saves a ton of typing and can be used to make code a lot easier to read.
In addition to the examples mentioned, type aliases (rather than namespace aliases) can be handy when repeatedly referring to generic types:
Dictionary<string, SomeClassWithALongName> foo = new Dictionary<string, SomeClassWithALongName>();
private void DoStuff(Dictionary<string, SomeClassWithALongName> dict) {}
Versus:
using FooDict = Dictionary<string, SomeClassWithALongName>;
FooDict foo = new FooDict();
private void DoStuff(FooDict dict) {}
Brevity.
There are fringe benefits to provide clarity between namespaces which share type names, but essentially it's just sugar.
I always use it in situations like this
using Utility = MyBaseNamespace.MySubNamsepace.Utility;
where Utility would otherwise have a different context (like MyBaseNamespace.MySubNamespace.MySubSubNamespace.Utility), but I expect/prefer Utility to always point to that one particular class.
It is very useful when you have multiple classes with the same name in multiple included namespaces. For example...
namespace Something.From.SomeCompanyA {
public class Foo {
/* ... */
}
}
namespace CompanyB.Makes.ThisOne {
public class Foo {
/* ... */
}
}
You can use aliases to make the compiler happy and to make things more clear for you and others on your team:
using CompanyA = Something.From.CompanyA;
using CompanyB = CompanyB.Makes.ThisOne;
/* ... */
CompanyA.Foo f = new CompanyA.Foo();
CompanyB.Foo x = new CompanyB.Foo();
We have defined namespace aliases for all of our namespaces. This makes it very easy to see where a class comes from, e.g:
using System.Web.WebControls;
// lots of other using statements
// contains the domain model for project X
using dom = Company.ProjectX.DomainModel;
// contains common web functionality
using web = Company.Web;
// etc.
and
// User from the domain model
dom.User user = new dom.User();
// Data transfer object
dto.User user = new dto.User();
// a global helper class
utl.SomeHelper.StaticMethod();
// a hyperlink with custom functionality
// (as opposed to System.Web.Controls.HyperLink)
web.HyperLink link = new web.HyperLink();
We have defined some guidelines how the aliases must be named and everyone is using them.
I find the aliases very useful in unit testing. When you are writing unit tests, it is a common practice to declare the subject to test as
MyClass myClassUT;
being myClassUT the subject Under Test. But what if you want to write unit tests for a static class with static methods? Then you can create an alias like this:
using MyStaticClassUT = Namespace.MyStaticClass;
Then you can write your unit tests like this:
public void Test()
{
var actual = MyStaticClassUT.Method();
var expected = ...
}
and you never loose sight of what the subject under test is.
In one way it is really handy while coding in Visual Studio.
Use-case: Let's say I've to use only few classes e.g. SqlConnection from a namespace System.Data. In normal course I'll import the System.Data.SqlClient namespace at the top of the *.cs file as shown below:
using System.Data;
Now look at my intellisense. It is heavily proliferated with whole lot of classes to choose from while typing in code editor. I'm not going to use whole bunch of classes at all:
So I would rather use an alias at the top of my *.cs file and get a clear intellisense view:
using SqlDataCon = System.Data.SqlClient.SqlConnection
Now look at my intellisense view. It is super-clear and super-clean.
One reason I know; It lets you use shorter names when you have name collisions from imported namespaces.
Example:
If you declared using System.Windows.Forms; and using System.Windows.Input; in the same file when you go to access ModifierKeys you might find that the name ModifierKeys is in both the System.Windows.Forms.Control and System.Windows.Input namespaces.
So by declaring using Input = System.Windows.Input; you can then get System.Windows.Input.ModifierKeys via Input.ModifierKeys.
I'm not a C# buff but aliasing namespace seems like "best practise" to me. That way you know what you're getting and still don't have to type too much more.
You can use them to modify a code very easily.
For example:
#if USE_DOUBLES
using BNumber = System.Double;
#else
using BNumber = System.Single;
#endif
public void BNumber DoStuff(BNumber n) {
// ...
}
public void BNumber DoStuff2(BNumber n) {
// ...
}
public void BNumber DoStuff3(BNumber n) {
// ...
}
By the simple change in of the directive you can decide if your whole code works in float or double.

Categories

Resources