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;
}
Related
What I'm looking for is a way to create a class (NotDefinedClass) with a simple bool variable and a "class variable" that I can declare in the constructor. The classes that I will declare in the constructor will have their own methods. And later I want to access theses methods like "ClassOne.CLASS1.MethodOne();"
public class NotDefinedClass
{
public bool Active;
public NotDefinedYetClass;
public NotDefinedClass(class _Class, bool _Active){
NotDefinedYetClass = _Class;
Active = _Active;
}
}
public NotDefinedClass ClassOne = new NotDefinedClass(CLASS1, false);
public NotDefinedClass ClassTwo = new NotDefinedClass(CLASS2, false);
public NotDefinedClass ClassThree = new NotDefinedClass(CLASS3, false);
Problem
A class is a type: we can't "assign a class to variable" in C#.
We can create an object instance being of type a class, or struct, and assign it to a variable:
var instanceOfMyClass = new MyClass();
Also we can get an instance of a Type class instance that describes the targetted class and assign it to a variable like:
var myClassType = instanceOfMyClass.GetType();
var myClassType = typeof(MyClass);
But what to do with that?
public Type NotDefinedYetClass;
And it is impossible to write this and replace T at runtime with something without using generics:
public T NotDefinedYetClass;
Also, it is impossible to use the keyword class as a type of a variable or method parameter:
public NotDefinedClass(class _Class, bool _Active)
Solution
A dynamic object can be used... or not: more information on goals and design may be needed.
public class NotDefinedClass
{
public bool Active;
public dynamic NotDefinedYetClass;
public NotDefinedClass(dynamic _Class, bool _Active)
{
NotDefinedYetClass = _Class;
Active = _Active;
}
}
Personally, I prefer generics to dynamics, except in a few cases where they are more powerfull and simpler.
We can create a generic version of the class to solve the problem using for example a T artifact as a generic type parameter that allows to create as many types as needed:
public class EmbededInstance<T> where T : class
{
public bool Active { get; /* private */ /* set; */ }
public T Instance { get; /* private */ /* set; */ }
public EmbededInstance(T instance, bool active)
{
Instance = instance;
Active = active;
}
}
Usage
public EmbededInstance<MyClass1> Embeded1
= new EmbededInstance<MyClass1>(new MyClass1(), false);
public EmbededInstance<MyClass2> Embeded2
= new EmbededInstance<MyClass2>(new MyClass2(), false);
public EmbededInstance<MyClass3> Embeded3
= new EmbededInstance<MyClass3>(new MyClass3(), false);
Having for example:
public class MyClass1
{
public void MyMethod() { }
}
public class MyClass2
{
public int MyInteger { get; set; }
}
public class MyClass3
{
}
To use the embeded instance members, properties and methods:
Embeded1.Instance.MyMethod();
Embeded2.Instance.MyInteger = 10;
More information
C# MSDoc
Generics in .NET
Generic classes and methods
Generics Level 1
Generics level 2
Just use Type for this:
public class NotDefinedClass
{
public bool Active;
public Type NotDefinedYetClass;
public NotDefinedClass(Type _Class, bool _Active){
NotDefinedYetClass = _Class;
Active = _Active;
}
}
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")
}
I'm trying to make a chemistry equation balancer thingy. For that I made a class Element:
class Element
{
public elemEnum ElemType {get; set;}
public double Amount {get; set;} // How many atoms of this type in the formula
}
*elemEnum is an Enum of all the chemical elements.
I wanted to make the set for ElemType parse a string to the enumeration, but since set can only take in values of the same type as value I decided to add a method:
public void SetElemType(string type)
{
this.ElemType = (elemEnum)Enum.Parse(typeof(elemEnum), type);
}
Is there an option to have the ElemType property be only set-able by the SetElemType method without having to make it private and adding a GetElemType method?
Since the most obvious solution from the comments has not been written as an answer:
Use a private setter.
class Element
{
public ElemEnum ElemType {get; private set;}
public double Amount {get; set;}
public void SetElemType(string type)
{
this.ElemType = (ElemEnum)Enum.Parse(typeof(ElemEnum), type);
}
}
This way, ElemType can only be set from within your own class.
without having to make it private
Well, you could create a workaround solution by adding a bool field to your class and modifying the property a little bit.
class Element
{
private bool _elemCanBeSet = false;
private elemNum _elemType;
public elemEnum ElemType
{
get { return _elemType; }
set { if (_elemCanBeSet) _elemType = value; }
}
public double Amount {get; set;} // How many atoms of this type in the formula
public void SetElemType(string type)
{
_elemCanBeSet = true;
this.ElemType = (elemEnum)Enum.Parse(typeof(elemEnum), type);
_elemCanBeSet = false;
}
}
This solution may confuse the developer using your class, because setting the property will have no effect. It is much better to use a private setter for your task, as stated by others. I just wanted to show an alternative approach.
As already was pointed, you can use private setter, alternatively you can use readonly property with public getter that works with field and method to modify this field :
class Element
{
private elemEnum _elemType;
public elemEnum ElemType { get { return _elemType; } }
public void SetElemType(string type)
{
this._elemType = (elemEnum)Enum.Parse(typeof(elemEnum), type);
}
public double Amount {get; } // How many atoms of this type in the formula
}
While it is practically the same as property with private setter it uses a slightly different approach...
Well if you really want to allow only one(!) method to change value you can use reflection and add class that envelopes your enum :
class MyElemSetter
{
private readonly elemEnum elem;
public MyElemSetter(elemEnum e, Action helperAction)
{
MethodInfo callingMethodInfo = helperAction.Method;
if (helperAction.Method.Name.Contains("<SetElemType>")) elem = e;
}
public static implicit operator elemEnum(MyElemSetter e)
{
return e.elem;
}
}
class Element
{
private MyElemSetter _elemType;
public elemEnum ElemType { get { return _elemType; } }
public void SetElemType(string type)
{
this._elemType = new MyElemSetter((elemEnum)Enum.Parse(typeof(elemEnum), type), () => { });
}
public double Amount { get; set; } // How many atoms of this type in the formula
}
I want to create a global accessible struct/class (in C#) to access my stock prices from the callback handler.
I know only C and it's easy there
Example in C
struct _Sample
{
int SomeValue;
};
struct _Sample Sample[10];
That's what I have so far in C# after 2 hours of trying.
public static class GlobalVar
{
private static double _StockPrice;
public static double SetStockPrice
{
set
{
_StockPrice = value;
}
}
public static double GetStockPrice
{
get
{
return _StockPrice;
}
}
}
The above example can be used as GlobalVar.SetStockPrice = 10.254; I know I have to use the <List> to make _StockPrice available as an array, but all my attempts to compile a working solution failed.
I would like to access it as GlobalVar[1].SetStockPrice = 1.0; and GlobalVar[1].SetStockPrice = 1.0;
I have to use C# because the SDK I'm using is only available in C#.
You would have to add a StockPrice class and keep an internal dictionary inside of GlobalVar to make this work, but you could use this:
public StockPrice this[int index]
{
get
{
StockPrice stockPrice = null;
if (index > -1)
{
InternalDictionary.TryGetValue(index, out stockPrice);
}
return stockPrice;
}
}
Then you can do GlobalVar[index] to get a certain StockPrice object from that internal dictionary of GlobalVar.
Also note that this will not work on a static class because static indexers are not allowed in C#. You might want to change your class to be a singleton instead of a static.
EDIT: A more complete example (still needs work though) with a singleton implementation:
public class GlobalVars
{
static StockPrices _stockPrices = new StockPrices();
public static StockPrices StockPrices
{
get
{
return _stockPrices ;
}
}
}
public class StockPrices
{
Dictionary<int, StockPrice> InternalDictionary = new Dictionary<int, StockPrice>();
public StockPrice this[int index]
{
get
{
StockPrice stockPrice = null;
if (index > -1)
{
InternalDictionary.TryGetValue(index, out stockPrice);
}
return stockPrice;
}
}
public void Add(StockPrice stockPrice)
{
int index = InternalDictionary.Keys.Max() + 1;
InternalDictionary.Add(index, stockPrice);
}
}
Then you could call your code like this:
GlobalVars.StockPrices[1].DoSomething
The C example you gave, is creating an array with 10 instances of the struct.
The equivalent C# code is this:
struct _Sample
{
public int SomeValue;
public static _Sample[] Sample = new _Sample[10];
};
That is not very C#-ish however. Using C# style I would write something like
struct Sample
{
public int SomeValue { get; set; }
public static Sample[] Values = new Sample[10];
}
You can do something like this to have the same behaviour like in c. Notice that you don't need to make SetField and GetField using { get; set; } you get this behaviour by default (it's a property).
public struct Sample
{
public double StockPrice { get; set; }
}
public static class GlobalVar
{
public static Sample[] Samples = new Sample[10];
}
And to acces use
GlobalVar.Samples[1].StockPrice = 1.0;
I have two constructors which feed values to readonly fields.
public class Sample
{
public Sample(string theIntAsString)
{
int i = int.Parse(theIntAsString);
_intField = i;
}
public Sample(int theInt) => _intField = theInt;
public int IntProperty => _intField;
private readonly int _intField;
}
One constructor receives the values directly, and the other does some calculation and obtains the values, then sets the fields.
Now here's the catch:
I don't want to duplicate the
setting code. In this case, just one
field is set but of course there may
well be more than one.
To make the fields readonly, I need
to set them from the constructor, so
I can't "extract" the shared code to
a utility function.
I don't know how to call one
constructor from another.
Any ideas?
Like this:
public Sample(string str) : this(int.Parse(str)) { }
If what you want can't be achieved satisfactorily without having the initialization in its own method (e.g. because you want to do too much before the initialization code, or wrap it in a try-finally, or whatever) you can have any or all constructors pass the readonly variables by reference to an initialization routine, which will then be able to manipulate them at will.
public class Sample
{
private readonly int _intField;
public int IntProperty => _intField;
private void setupStuff(ref int intField, int newValue) => intField = newValue;
public Sample(string theIntAsString)
{
int i = int.Parse(theIntAsString);
setupStuff(ref _intField,i);
}
public Sample(int theInt) => setupStuff(ref _intField, theInt);
}
Before the body of the constructor, use either:
: base (parameters)
: this (parameters)
Example:
public class People: User
{
public People (int EmpID) : base (EmpID)
{
// Add more statements here.
}
}
I am improving upon supercat's answer. I guess the following can also be done:
class Sample
{
private readonly int _intField;
public int IntProperty
{
get { return _intField; }
}
void setupStuff(ref int intField, int newValue)
{
//Do some stuff here based upon the necessary initialized variables.
intField = newValue;
}
public Sample(string theIntAsString, bool? doStuff = true)
{
//Initialization of some necessary variables.
//==========================================
int i = int.Parse(theIntAsString);
// ................
// .......................
//==========================================
if (!doStuff.HasValue || doStuff.Value == true)
setupStuff(ref _intField,i);
}
public Sample(int theInt): this(theInt, false) //"false" param to avoid setupStuff() being called two times
{
setupStuff(ref _intField, theInt);
}
}
Here is an example that calls another constructor, then checks on the property it has set.
public SomeClass(int i)
{
I = i;
}
public SomeClass(SomeOtherClass soc)
: this(soc.J)
{
if (I==0)
{
I = DoSomethingHere();
}
}
Yeah, you can call other method before of the call base or this!
public class MyException : Exception
{
public MyException(int number) : base(ConvertToString(number))
{
}
private static string ConvertToString(int number)
{
return number.toString()
}
}
Constructor chaining i.e you can use "Base" for Is a relationship and "This" you can use for same class, when you want call multiple Constructor in single call.
class BaseClass
{
public BaseClass():this(10)
{
}
public BaseClass(int val)
{
}
}
class Program
{
static void Main(string[] args)
{
new BaseClass();
ReadLine();
}
}
When you inherit a class from a base class, you can invoke the base class constructor by instantiating the derived class
class sample
{
public int x;
public sample(int value)
{
x = value;
}
}
class der : sample
{
public int a;
public int b;
public der(int value1,int value2) : base(50)
{
a = value1;
b = value2;
}
}
class run
{
public static void Main(string[] args)
{
der obj = new der(10,20);
System.Console.WriteLine(obj.x);
System.Console.WriteLine(obj.a);
System.Console.WriteLine(obj.b);
}
}
Output of the sample program is
50 10 20
You can also use this keyword to invoke a constructor from another constructor
class sample
{
public int x;
public sample(int value)
{
x = value;
}
public sample(sample obj) : this(obj.x)
{
}
}
class run
{
public static void Main(string[] args)
{
sample s = new sample(20);
sample ss = new sample(s);
System.Console.WriteLine(ss.x);
}
}
The output of this sample program is
20
Error handling and making your code reusable is key. I added string to int validation and it is possible to add other types if needed. Solving this problem with a more reusable solution could be this:
public class Sample
{
public Sample(object inputToInt)
{
_intField = objectToInt(inputToInt);
}
public int IntProperty => _intField;
private readonly int _intField;
}
public static int objectToInt(object inputToInt)
{
switch (inputToInt)
{
case int inputInt:
return inputInt;
break;
case string inputString:
if (!int.TryParse(inputString, out int parsedInt))
{
throw new InvalidParameterException($"The input {inputString} could not be parsed to int");
}
return parsedInt;
default:
throw new InvalidParameterException($"Constructor do not support {inputToInt.GetType().Name}");
break;
}
}
Please, please, and pretty please do not try this at home, or work, or anywhere really.
This is a way solve to a very very specific problem, and I hope you will not have that.
I'm posting this since it is technically an answer, and another perspective to look at it.
I repeat, do not use it under any condition. Code is to run with LINQPad.
void Main()
{
(new A(1)).Dump();
(new B(2, -1)).Dump();
var b2 = new B(2, -1);
b2.Increment();
b2.Dump();
}
class A
{
public readonly int I = 0;
public A(int i)
{
I = i;
}
}
class B: A
{
public int J;
public B(int i, int j): base(i)
{
J = j;
}
public B(int i, bool wtf): base(i)
{
}
public void Increment()
{
int i = I + 1;
var t = typeof(B).BaseType;
var ctor = t.GetConstructors().First();
ctor.Invoke(this, new object[] { i });
}
}
Since constructor is a method, you can call it with reflection. Now you either think with portals, or visualize a picture of a can of worms. sorry about this.
In my case, I had a main constructor that used an OracleDataReader as an argument, but I wanted to use different query to create the instance:
I had this code:
public Subscriber(OracleDataReader contractReader)
{
this.contract = Convert.ToString(contractReader["contract"]);
this.customerGroup = Convert.ToString(contractReader["customerGroup"]);
this.subGroup = Convert.ToString(contractReader["customerSubGroup"]);
this.pricingPlan= Convert.ToString(contractReader["pricingPlan"]);
this.items = new Dictionary<string, Member>();
this.status = 0;
}
So I created the following constructor:
public Subscriber(string contract, string customerGroup) : this(getSubReader(contract, customerGroup))
{ }
and this method:
private static OracleDataReader getSubReader(string contract, string customerGroup)
{
cmdSubscriber.Parameters[":contract"].Value = contract + "%";
cmdSubscriber.Parameters[":customerGroup"].Value = customerGroup+ "%";
return cmdSubscriber.ExecuteReader();
}
notes: a statically defined cmdSubscriber is defined elsewhere in the code; My main constructor has been simplified for this illustration.
In case you need to run something before calling another constructor not after.
public class Sample
{
static int preprocess(string theIntAsString)
{
return preprocess(int.Parse(theIntAsString));
}
static int preprocess(int theIntNeedRounding)
{
return theIntNeedRounding/100;
}
public Sample(string theIntAsString)
{
_intField = preprocess(theIntAsString)
}
public Sample(int theIntNeedRounding)
{
_intField = preprocess(theIntNeedRounding)
}
public int IntProperty => _intField;
private readonly int _intField;
}
And ValueTuple can be very helpful if you need to set more than one field.
NOTE: most of the solutions above does not work for structs.
Unfortunately initializing struct fields in a method called by a constructor is not recognized by the compiler and will lead to 2 errors:
in the constructor: Field xxxx must be fully assigned...
in the method, if you have readonly fields: a read-only field cannot be assigned except in a constructor.
These can be really frustrating for example when you just need to do simple check to decide on which constructor to orient your call to.