Assuming there's an enumeration defined as follows:
public enum Beep
{
HeyHo,
LetsGo
}
I wonder if it's possible to improve the following property:
public Dictionary<Beep, String> Stuff{ get; set; }
...
String content = Stuff[Beep.HeyHo]
because the way it's right now, I retrieve the dictionary and then pick out the element I need. I wonder if it's (a) possible at all and if so (b) recommended to create something like this pseudo-code.
public String Stuff{ get<Beep>; set<Beep>; }
...
String content = Stuff[Beep.HeyHo]
You can apply an indexer to your class.
It is recommended, as it improves encapsulation. For example, it's perfectly possible using the original code to replace the Dictionary entirely with a different dictionary - which is probable not desirable.
public class MyClass
{
// Note that dictionary is now private.
private Dictionary<Beep, String> Stuff { get; set; }
public String this[Beep beep]
{
get
{
// This indexer is very simple, and just returns or sets
// the corresponding element from the internal dictionary.
return this.Stuff[beep];
}
set
{
this.Stuff[beep] = value;
}
}
// Note that you might want Add and Remove methods as well - depends on
// how you want to use the class. Will client-code add and remove elements,
// or will they be, e.g., pulled from a database?
}
Usage:
MyClass myClass = new MyClass();
string myValue = myClass[Beep.LetsGo];
You can also use an indexer.
class MyClass
{
private readonly Dictionary<Beep, string> _stuff = new Dictionary<Beep, string>();
public string this[Beep beep]
{
get { return _stuff[beep]; }
set { _stuff[beep] = value; }
}
}
Now, instead of calling
var obj = new MyClass();
string result = obj.Stuff[Beep.HeyHo];
You can call
var obj = new MyClass();
string result = obj[Beep.HeyHo];
Indexers work much like properties but have at least one argument used as index. You can have only one indexer per class, however you can create different overloads of it. The same overloading rules apply as for methods.
Something like this using Indexer
public class Stuff
{
public Dictionary<Beep, String> _stuff { get; set; }
public enum Beep
{
HeyHo,
LetsGo
}
public Stuff()
{
_stuff = new Dictionary<Beep, string>();
// add item
_stuff[Beep.HeyHo] = "response 1";
_stuff[Beep.LetsGo] = "response 2";
}
public string this[Beep beep]
{
get { return _stuff[beep]; }
}
}
Sample Usage :
public static class Program
{
private static void Main()
{
Stuff stuff = new Stuff();
string response;
response = stuff[Stuff.Beep.HeyHo]; // response 1
response = stuff[Stuff.Beep.LetsGo]; // response 2
}
}
Related
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.
public class Program
{
public static void Main(string[] args)
{
var c = check.myValue("Example 1"); //This is the pattern I've to use, don't want to create an object (Is it possible to use it with static class)
Console.WriteLine(c.result1);
Console.WriteLine(c.result2);
}
}
public static class check
{
public static void myValue(string qr)
{
public string result1 = "My Name" + qr;
public string result1 = "You're" + qr;
}
}
See here Online Example (Code is not working)
Every thing on main function I've to use exactly the same pattern because I'll use it in a lot of different classes and I don't want to create object each and every time by using non-static class.
Please correct me if I'm wrong
There's a lot wrong with the syntax of that code, which #Sergey addresses in his answer.
You appear to want to return an instance of a class from a static method, and that class should contain two properties.
You can do that by creating the actual, nonstatic class containing the properties:
public class Check
{
public string Result1 { get; set; }
public string Result2 { get; set; }
}
Then return a new instance from the static method therein:
public static Check MyValue(string qr)
{
var result = new Check();
result.Result1 = "My Name" + qr;
result.Result2 = "You're" + qr;
return result;
}
However, you're saying in the comments in your code that you don't want to use an object.
In that case it appears you want to use static properties. That's generally not recommendable, but it would look like this:
public static class Check
{
public static string Result1 { get; set; }
public static string Result2 { get; set; }
public static void MyValue(string qr)
{
Result1 = "My Name" + qr;
Result2 = "You're" + qr;
}
}
Then you can read Check.Result1 after calling the method MyValue().
Your code is totally wrong
myValue method returns void. You cannot assign void return value to variable.
You cannot have public modifiers for local variables.
You cannot have local variables with same name in same scope
If you want to return two values from method, then you should return object with two fields - custom class or tuple. You can also use out parameters, but I don't think it's your case
public static class Check
{
public static Tuple<string, string> MyValue(string qr)
{
return Tuple.Create($"My Name {qr}", $"You're {qr}");
}
}
With C# 7 it's a little bit better. You can write this method in one line and provide names for tuple properties
(string MyName, string YourName) MyValue(string qr) => ($"My Name {qr}", $"You're {qr}");
Usage
var result = Check.MyValue("Example 1");
Console.WriteLine(result.Item1); // result.MyName
Console.WriteLine(result.Item2); // result.YourName
You can practice with creating custom class with nicely named properties instead of using tuples.
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 class which have too many related calculated properties.
I have currently kept all properties are read only.
some properties need long calculation and it is called again when its related properties are needed.
How can create this complex object .Also i want these properties should not be set from external code. I need show hide as i am binding properties for UI. Also i think order is also important.
My Class is something like
public string A
{
get
{
return complexMethod();
;
}
}
public string B
{
get
{
if (A == "value")
return "A";
else return "B";
;
}
}
public bool ShowHideA
{
get
{
return string.IsNullOrEmpty(A);
;
}
}
public bool ShowHideB
{
get
{
return string.IsNullOrEmpty(B);
;
}
}
public string complexMethod()
{
string value = "";
// calculation goes here
return value;
}
}
Thanks
You need to use Lazy type provided by .net:
Lazy<YourType> lazy = new Lazy<YourType>();
Make your properties internal to not be set from external code.
Well tall order isn't it?
One of the coolest things about extension methods is you can use types. This is perfect for writing external programs to calculate property values. Start like this...
public static class XMLibrary
{
public static MC CalculateValues(this MC myclass)
{
//for each property calculate the values here
if (myclass.Name == string.Empty) myclass.Name = "You must supply a name";
if (myclass.Next == 0) myclass.Next = 1;
//when done return the type
return myclass;
}
}
public class MC
{
public string Name { get; set; }
public int Next { get; set; }
}
public class SomeMainClass
{
public SomeMainClass()
{
var mc = new MC { Name = "test", Next = 0 };
var results = mc.CalculateValues();
}
}
There are many other ways to do class validation on a model, for example dataannotations comes to mind, or IValidatableObject works too. Keeping the validation separate from the class is a good idea.
//Complex properites are simple
public class MyComplextClass{
public List<MyThings> MyThings {get;set;}
public List<FileInfo> MyFiles {get;set;}
public List<DateTime> MyDates {get;set;}
}
I want to access a string from one class to another. I have used the property method as follows -
Myclass.cs
public class MyClass
{
private string _user;
public string user
{ get { return this._user; } set { this._user = value; } }
}
consumption.aspx.cs
I am assigning the value to user in a function
MyClass m = new MyClass();
m.user = "abc"
Now when I try to use this value in my another function which is called after this value is assigned
RawDal.cs
MyClass m = new MyClass();
string x = m.user;
I get empty value... How to do it?
As already mentioned in the comments you are creating two separate instances of MyClass which results simplified in something like:
int a;
a = 3;
int b;
Console.WriteLine("a: " + b); //<-- here it should be obvious why b is not 3
You can work around this in 3 ways:
1) Use the same instance of MyClass for the second call, but in this case you need to be in the same scope or pass the instance on to the new scope.
2) Make the property/member static:
public class MyClass
{
public static string User { get; set; } //the "static" is the important keyword, I just used the alternative property declaration to keep it shorter
}
Then you can access the same User value everywhere via MyClass.User.
3) Use a singleton:
public class MyClass
{
private static MyClass instance = null;
public static MyClass Instance
{
get
{
if(instance == null)
instance = new MyClass();
return instance;
}
}
public string User { get; set; }
}
Then you can access it via MyClass.Instance.User.
There are possibly some more solutions, but these are the common ones.
You are not using the same instance. Try
public class MyClass
{
private string _user;
public string user
{ get { return this._user; } set { this._user = value; } }
}
public string YourFunction()
{
MyClass m = new MyClass();
m.user = "abc"
return m.user;
}
If all you want to return is a string try something like
string x = YourFunction();