Get values from object through class - c#

public class BlockType
{
public static BlockType Dirt_Block = new Block("Blah! values here");
}
public struct Block
{
public static string Value;
public Block(string value)
{
value = value;
}
}
Is there any way I can get the value from DirtBlock? BlockType.Dirt_Block.Value Dosent work, Im not sure if this is possible, if not any ways to get the same result? (Theres more values, but I shortened it for size) Btw, Im accessing BlockType.Dirt.value from anouther class. I only want to get one value out of it though

That's because Dirt_Block is a BlockType, not a Block. In fact, I wouldn't expect this code to compile, as there is no way of converting a Block to a BlockType.
I'm not quite sure what you're after, but it sounds like you have a collection of block types that would suit an enumeration:
public enum BlockType
{
Dirt,
Wood,
Metal
}
and you have a collection of Blocks that each have a block type:
public class Block
{
public BlockType Type { get; set; }
}
Here, we are using a public auto property. You should avoid using public fields (no getters or setters).
Now, to create a new Block, you can use object initialisation:
var block = new Block { Type = BlockType.Metal };
Alternatively, you could create a Block constructor which takes a BlockType parameter.

Other way to achieve it.
I think this approah provides an easier way to load/save tilemaps, and let defining block properties from text if needed.
Strict OOP with virtual methods and intensive inheritance is not a good idea for a game that may need optimizations to run fine.
Of course it can be improved or done in other way. ;)
public struct BlockProperty
{
public Texture2D Texture;
public string Name;
}
public class BlockProperties
{
static readonly List<BlockProperty> Blocks;
public static readonly BlockProperty Dirt;
public static readonly BlockProperty Grass;
public static readonly BlockProperty Wall;
static BlockProperties( )
{
ContentManager Content = Game1.Instance.Content;
Blocks = new List<BlockProperty>( )
{
(Dirt = new BlockProperty( ) { Name = "Dirt", Texture = Content.Load<Texture2D>( "textures/dirt" ) }),
(Grass = new BlockProperty( ) { Name = "Grass", Texture = Content.Load<Texture2D>( "textures/grass" ) }),
(Wall = new BlockProperty( ) { Name = "Wall", Texture = Content.Load<Texture2D>( "textures/wall" ) }),
};
}
public static BlockProperty ByName( string name )
{
return Blocks.FirstOrDefault( b => b.Name == name );
}
}
public class Block
{
public BlockProperty BlockType;
pulic Vector2 Position;
public Block( BlockProperty block )
{
this.BlockType = block;
}
public Block( string block )
{
this.BlockType = BlockProperties.ByName(block);
}
}
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
public static Game1 Instance { get; private set; }
Block Block;
public Game1( )
{
Instance = this;
graphics = new GraphicsDeviceManager( this );
}
protected override void LoadContent( )
{
Block = new Block("Dirt") { Position = new Vector2(100,100) };
}
}

Assuming you mean Dirt_Block to be of type Block - your Block Value field is static - that means it is associated with the Block type, not any particular instance. Make it a public field (or property) and your access will work:
public class BlockType
{
public static Block Dirt_Block = new Block("Blah! values here");
}
public struct Block
{
public string Value;
public Block(string value)
{
value = value;
}
}
Also if there is no particular reason you are going with a struct here, I would suggest making Block a class and expose Value as a public property.

Your doubt isn't very clear... but I think what you want is something like this... using OOP paradigm on the block classes.
public class BlockType
{
public virtual string Value;
public static BlockType Dirt = new Block("Blah! values here");
}
public class Block : BlockType
{
private string value;
public Block(string value)
{
this.value = value;
}
public string Value
{
get { return value; }
}
}
Right?

Related

load static fields in class

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.

in C#, can a derived value be referred to by both static and instance methods/properties?

I'm quite new to C#, and I've been banging my head against a wall trying to figure out how to implement a certain design pattern related to instance and static properties returning the same value out of a derived class. It seems like there might be restrictions in place keeping this from happening, so I wanted to explain my issue to see if anyone has thoughts on how to solve this problem.
public class Resource {
protected static float s_unitMass = 1.0f;
protected static string s_name = "<Resource>";
public int quantity;
// Class Convenience
static public float GetUnitMass() {
return s_unitMass;
}
static public string GetName() {
return s_name;
}
// Instance Convenience
virtual public float totalMass {
get { return s_unitMass * quantity; }
}
virtual public float unitMass {
get { return s_unitMass; }
}
virtual public string name {
get { return s_name; }
}
}
public class Iron : Resource {
new protected static s_unitMass = 2.0f;
new protected static s_name = "Iron";
}
This code very much does not work (the values for the base class Resource are always returned), but I'm writing it out this way to indicate what I would like to do... Have a value that can be referred to by both:
string name = Iron.GetName();
float unitMass = Iron.GetUnitMass();
and
Iron iron = new Iron();
string name = iron.name;
float unitMass = iron.unitMass;
float totalMass = iron.totalMass;
If this is really desired, then
// Have a [static] singleton Iron instance, but doesn't prevent
// creation of new Iron instances..
static class ResourceTable {
public static Iron Iron = new Iron();
};
// Just an Iron instance; it doesn't matter where it comes from
// (Because it is a 'singleton' the SAME instance is returned each time.)
Iron iron = ResourceTable.Iron; // or new Iron();
// [^- object ]
// .. and it can be used the same
string name = iron.name; // or ResourceTable.Iron.name, eg.
float unitMass = iron.unitMass; // [^- object too! ]
float totalMass = iron.totalMass;
Now, for some notes.
Generally a singleton doesn't allow "alternative methods of creation"; and mutable singletons are .. icky; and,
This is over-specialization of types (e.g Iron, Feather, ..); and,
The element type (which is relates to a particular mass eg.) should probably be separate from the quantity, as there may be multiple quantities associated with a resource throughout a problem.
Consider:
static Resource {
public string Name { get; set; }
public float UnitMass { get; set; }
}
static Bucket {
public Resource FilledWith { get; set; }
public int Quantity { get; set; }
public float TotalMass {
get { return FilledWith.UnitMass * Quantity; }
}
}
static class ResourceTable {
public Resource Iron =
new Resource { Name = "Iron", UnitMass = 1 };
public Resource Feather =
new Resource { Name = "Feather", UnitMass = 0.1 };
}
var aBucket = new Bucket {
FilledWith = ResourceTable.Iron,
Quantity = 100
};

"Read-only" public properties without setters/getters

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;
}

Design a mutable class that after it's consumed becomes immutable

Suppose that the scenario doesn't allow to implement an immutable type. Following that assumption, I'd like opinions / examples on how to properly design a type that after it's consumed, becomes immutable.
public class ObjectAConfig {
private int _valueB;
private string _valueA;
internal bool Consumed { get; set; }
public int ValueB {
get { return _valueB; }
set
{
if (Consumed) throw new InvalidOperationException();
_valueB = value;
}
}
public string ValueA {
get { return _valueA; }
set
{
if (Consumed) throw new InvalidOperationException();
_valueA = value;
}
}
}
When ObjectA consumes ObjectAConfig:
public ObjectA {
public ObjectA(ObjectAConfig config) {
_config = config;
_config.Consumed = true;
}
}
I'm not satisfied that this simply works, I'd like to know if there's a better pattern (excluded, as said, making ObjectAConfig immutable by design from begin).
For example:
can make sense define a monad like Once<T> that allow the wrapped value to be initialized only once?
can make sense define a type that returns the type itself changing a private field?
What you are implementing sometimes goes under the name "popsicle immutability" - i.e. you can freeze it. Your current approach will work - indeed I use that pattern myself in numerous places.
You can probably reduce some duplication via something like:
private void SetField<T>(ref T field, T value) {
if (Consumed) throw new InvalidOperationException();
field = value;
}
public int ValueB {
get { return _valueB; }
set { SetField(ref _valueB, value); }
}
public string ValueA {
get { return _valueA; }
set { SetField(ref _valueA, value); }
}
There is another related approach, though: a builder. For example, taking your existing class:
public interface IConfig
{
string ValueA { get; }
int ValueB { get; }
}
public class ObjectAConfig : IConfig
{
private class ImmutableConfig : IConfig {
private readonly string valueA;
private readonly int valueB;
public ImmutableConfig(string valueA, int valueB)
{
this.valueA = valueA;
this.valueB = valueB;
}
}
public IConfig Build()
{
return new ImmutableConfig(ValueA, ValueB);
}
... snip: implementation of ObjectAConfig
}
Here there is a truly immutable implementation of IConfig, and your original implementation. If you want the frozen version, call Build().

Call one constructor from another

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.

Categories

Resources