What I have is:
public static class IDs {
public static string someID { get; set; }
static IDs() {
log.info(someID);
// use someID here
}
}
public class otherClass {
public void otherMethod(string sym) {
IDs.someID = sym;
}
}
and then using an instance of otherClass like this:
otherClassInstance.otherMethod("someStringSymbol");
I dont have any build errors, but log.info(someID); is printing null.
I was expecting it to be someStringSymbol.
This is because the static constructor is called automatically before the first instance is created or any static members are referenced..
This means that when an instance of otherClass invokes IDs.someID = sym; the first operation that gets executed is the static constructor, i.e. the code inside static IDs().
At this point the static variable has not yet been initialized, and you are basically executing log.info(null);.
After the static constructor completes, the variable is initialized, so you should be able to see its value inside otherMethod, after the first reference of IDs.
Given the OP's requirement:
I want to use the value passed in someID in a switch statement
The solution could be to simply execute a static method whenever a new value is set, with the help of explicit getters and setters:
public static class IDs
{
private static string _someID; // backing field
public static string SomeID
{
get { return _someID; }
set
{
_someID = value;
DoSomethingWithSomeID();
}
}
private static DoSomethingWithSomeID()
{
// Use SomeID here.
switch (IDs.SomeID)
{
...
}
}
}
public class OtherClass
{
public void OtherMethod(string sym)
{
// This will set a new value to the property
// and invoke DoSomethingWithSomeID.
IDs.SomeID = sym;
}
}
DoSomethingWithSomeID will be invoked every time someone sets a new value to SomeID.
I dont think what you are trying to do is suited to static classes. I would try the following
public class IDs{
public string someID{ get; set; }
public IDs(string someId){
this.someID = someId;
log.info(this.someID);
//use someID here
}
}
pulic class otherClass{
public otherMethod(string sym){
IDs id = new IDs(sym);
}
}
public class anotherClass{
//access instance of otherClass in wrp and call otherMethod()
wrp.otherMethod("someStringSymbol")
}
Related
public int userID;
//global variable
public Index()
{
userID = 10;
return userID;
}
public TaskCompleted()
{
Console.WriteLine(Index())
}
i want the userID to be accessed in each and every method and can we updated anywhere
Your Index method has two problems.
Syntax problem: Every method must have a return type. Either a real type like int or the void keyword.
public int Index()
Semantic problem. At every call it sets userID and returns it. Why store the value in this variable? It will be replaced by a new value at the next call and could just be a local variable (i.e., a variable inside the method) or be dismissed completely. But maybe your example was simply not complete.
Let's try different approaches:
Passing value through a class field (your "global" variable).
private int _userId;
public void SetUserId() // `void` means that the method is not returning a value.
{
_userId = 10;
}
public void PrintUserId()
{
Console.WriteLine(_userId);
}
This requires you to call SetUserId(); before calling PrintUserId();
Let the method return the value.
public int GetUserId() // `int` means that the method is returning an `int` value
{
return 10;
}
public void PrintUserId()
{
Console.WriteLine(GetUserId());
}
Combine the two previous approaches
private int _userId;
public void SetUserId()
{
_userId = 10;
}
public int GetUserId()
{
return _userId;
}
public void PrintUserId()
{
Console.WriteLine(GetUserId());
}
C# has a concept called "property". A property is a set of "Get" and "Set" methods, just as in the previous example, but with as special syntax.
private int _userId;
public UserId
{
get { return _userId; }
set { _userId = value; }
}
public void PrintUserId()
{
Console.WriteLine(UserId);
}
A property having no additional logic besides assigning and returning a value can also be implemented as an auto-property.
public int UserId { get; set; } // A hidden field is automatically created.
The caller would have to do something like this:
var obj = new MyClass();
obj.UserId = 10;
obj.PrintUserId();
You can use a static property of a static class:
public static class Globals
{
public static int UserID {get; set;}
}
Usage: var userId = Globals.UserID;
I have a class with some static filds. When they are initialised they add themself to a Dictionary.
When the program starts a second time it tries to access the content of the Dictionary but since I haven't accessed any filds in the class (the Dictionary is in another) they can't be found.
I already understand that the static fields are initialised when I access one of them but are there any other ways to initialise them without calling any methods or fields for no other reason then nitialising them once?
----------------------
Here some code:
Resource.cs
public class Resource : InventoryItem
{
public const int IDBase = 1000000;
private Resource(int id) : base(IDBase + id) { }
public static Resource Hydrogen { get; } = new Resource(1); // H
public static Resource Helium { get; } = new Resource(2); // He
public static Resource Lithium { get; } = new Resource(3); // Li
public static Resource Beryllium { get; } = new Resource(4); // Be
public static Resource Boron { get; } = new Resource(5); // B
public static Resource Carbon { get; } = new Resource(6); // C
public static Resource Nitrogen { get; } = new Resource(7); // N
public static Resource Oxygen { get; } = new Resource(8); // O
// and all the other elements....
}
}
InventoryItem.cs
public abstract class InventoryItem
{
public int ID { get; }
private static readonly Dictionary<int, InventoryItem> idList = new Dictionary<int, InventoryItem>();
public InventoryItem(int id)
{
ID = id;
idList[id] = this;
}
public static InventoryItem GetFromID(int id)
{
return idList[id];
}
}
When I use InventoryItem.GetFromID(int id) before accessing anything from the Resource class the dictionary is empty and nothing can be found. If I access any resource before they are in the Dictionary.
As the static fields in a class are only initialized when you first use that class, you have to somehow force this initialization, e.g. by calling any static method in Resource.
Example:
in Resource, add
public static void Initialize()
{
// can be left empty; just forces the static fields to be initialized
}
and somewhere else in your project
Resource.Initialize();
Alternatively you could initialize them in a static constructor.
It's like a default constructor except it is static.
It is similar to Java's static { ... } block
public class Resource : InventoryItem
{
public const int IDBase = 1000000;
public static Resource Hydrogen { get; }
public static Resource Helium { get; }
public static Resource Lithium { get; }
// ...
private Resource(int id) : base(IDBase + id)
{
}
private static Resource()
{
Hydrogen = new Resource(1);
Helium = new Resource(2);
Lithium = new Resource(3);
// etc...
}
}
Caveat - I haven't actually tried this but I think it's likely to work.
Static fields and properties are initialized in a type constructor, regardless of how you write it, so both:
static Resource()
{
Hydrogen = new Resource(1);
}
and
Hydrogen { get; } = new Resource(1);
Are the same thing, the only difference is the initialization order, also it would allow you to call static fuctions, but in OP's case it really doesn't make a difference, that's why pamcevoy's answer won't work.
Klaus provides a valid way of doing things, and it will work, just you would need to call the Initialize method before your GetFromID, at least once, as to initialize all of the Resource class's static properties, e.g.:
Resource.Initialize();
InventoryItem.GetFromID(id);
Your last option is to do method shadowing, basically add to your Resource class the same GetFromID method with the new operator and then call GetFromID through the Resource class, e.g.
public class Resource : InventoryItem
{
public static new InventoryItem GetFromID(int id)
{
return InventoryItem.GetFromID(id);
}
}
But know that method shadowing isn't the same as overriding a method, so if you call InventoryItem.GetFromID you won't be calling Resource.GetFromID. This will eliminate the need for calling at startup a separate Initialize method in the Resource class but, it will force you to, at least once, call GetFromID through the Resource class.
Update: At the end of the day, the only way to initialize static fields/props is by accessing one thing or another in said class.
Does C# have such a feature (like Python's getter-only pattern)?
class A
{
public [read-only] Int32 A_;
public A()
{
this.A_ = new Int32();
}
public A method1(Int32 param1)
{
this.A_ = param1;
return this;
}
}
class B
{
public B()
{
A inst = new A().method1(123);
Int32 number = A.A_; // okay
A.A_ = 456; // should throw a compiler exception
}
}
To obtain this I could use the private modifier on the A_ property, and only implement a getter method. Doing so, in order to access that property I should always make a call to the getter method... is it avoidable?
Yes that is possible, syntax is like this:
public int AProperty { get; private set; }
yes. you can use read only property with private setter.
Using Properties - msdn
public string Name
{
get;
private set;
}
I have a static class like this:
public static class ApplicationList
{
public static List<ApplicationsModel> ApplicationsModels { get; set; }
}
I want to use ApplicationsModels in another class
class Program
{
static void Main(string[] args)
{
GetApplicationNameFromAppConfigAndAddToApplicationList();
}
private static void GetApplicationNameFromAppConfigAndAddToApplicationList()
{
List<string> applicationName = ConfigurationManager.AppSettings["AppName"].Split(',').ToList();
foreach (var variable in applicationName)
{
ApplicationList.ApplicationsModels.Add(new ApplicationsModel { DateTime = DateTime.MinValue, Name = variable });
}
}
}
But i my ApplicationList is null and get this error
Object reference not set to an instance of an object.
This is static Prpoerty and we can't create instance form static Prpoerty
Well you have a
public static List<ApplicationsModel> ApplicationsModels { get; set; }
property which is not initialized.
Can do something like this, instead:
public static class ApplicationList
{
private static List<ApplicationsModel> appmodel = new List<ApplicationsModel>();
public static List<ApplicationsModel> ApplicationsModels
{
get { return appmodel ;}
}
//DON'T THINK YOU NEED A SET IN THIS CASE..
// BUT ADD IT, IF NEED
}
You get the null reference exception because the List<ApplicationsModel> ApplicationsModels is still null when you try to use it. Just declaring it as static doesn't means that the compiler or the framework adds for you the call to
ApplicationsModels = new List<ApplicationsModel>();
Short answer, add this line before loading your list:
ApplicationsModels = new List<ApplicationsModel>();
Longer answer:
You need to initialise your List before you can add to it.
This is because a (reference-type) property will be null by default, and it wouldn't make sense to do null.Add(item).
Solution 1: Initialise before loading:
The easy solution is to add an initialisation line before loading your list in your Get... method:
ApplicationsModels = new List<ApplicationsModel>();
However, this will reinitialise the list each time you call the Get method (which may or may not be what you want). You could place a check to only recreate the list if it is null, but if that's the behaviour you're after I'd lean towards one of the other solutions below.
Solution 2: Use an initialised field instead of a property:
Another way is to replace your property with an initialised field. Either:
public static List<ApplicationsModel> ApplicationsModels = new List<ApplicationsModel>();
Or:
public static List<ApplicationsModel> ApplicationsModels
{
get { return _applicationsModels; }
set { _applicationModels = value; } // Do you really want a set?
}
private static List<ApplicationsModel> _applicationsModels = new List<ApplicationsModel>();
Solution 3: Keep a property, but use a static constructor:
Another way is to use a static constructor in ApplicationList:
static ApplicationList()
{
ApplicationsModels = new List<ApplicationsModel>();
}
Can somone explain why I get this error on this code?
Error 1 The type
'ConsoleApplication1.TestClass'
already contains a definition for
'IsThisOK'
class TestClass
{
public bool IsThisOK { get; set; }
public static bool IsThisOK(string str)
{
return true;
}
public static void Test()
{
TestClass c = new TestClass();
c.IsThisOK = IsThisOK("Hello");
}
}
You're trying to define a property and a method with the same name. While you can have multiple methods that override each other (with different argument lists), you cannot have a property and a method that share the same name
You've declared IsThisOK twice, at line 3 and line 5 (property and static function).
Try to imagine how could the compiler could figure out to which you are referring later on?
Because you cannot provide same name to a function and a Property.
You cannot overload function with property.
You can use it in this way:
class TestClass
{
public bool IsThisOK { get; set; }
public static bool isThisOK(string str)
{
return true;
}
public static void Test()
{
TestClass c = new TestClass();
c.IsThisOK = isThisOK("Hello");
}
}
As other pointed out, you cannot have a method and a property with the same name.
However, you can more or less work around this by using an extension method if you like:
static class TestClassExtension
{
public static bool IsThisOK(this TestClass, string str)
{
return true;
}
}
class TestClass
{
public bool IsThisOK { get; set; }
public static void Test()
{
TestClass c = new TestClass();
c.IsThisOK = this.IsThisOK("Hello");
}
}