How can I access private members from other classes? - c#

I'm not that new to C# but don't have as much experience as in Java.
As you know, in Java, we can access all the private members from outer classes.
So I tried the same thing in C# because I had some fields and methods needed to be accessed from only inside my plugin library and didn't want it to be shown to users. A simple example can be like this.
public static class StaticClass {
public class InstanceClass {
private int oldValue;
public int Value;
}
public static void Backup(InstanceClass ic) {
ic.oldValue = ic.Value;
}
public static void Restore(InstanceClass ic) {
ic.Value = ic.oldValue;
}
}
If I make the field oldValue public, then it'll be mess and look dirty when end users use the plugin. It doesn't have to be an Inner class or in a some specific form. I just want to know if there is any way to control or access private members of an instance from other static classes in the same assembly only by me.

For allowing access only within assembly use internal modifier.
public class InstanceClass {
internal int oldValue;
public int Value;
}

This is not possible in C#. The container class has no special access over the nested class.
You can access private members of the container from the nested class, but not vice versa. The pattern you're trying to use simply isn't used in C# - it's a violation of member accessibility. There are some hacks to force the Java pattern on C# (using reflection or abusing interfaces), but they are just that - hacks.
The "cleanest" approach might look something like this:
public static class StaticClass
{
private interface IInstanceClassInternal
{
int OldValue { get; set; }
}
public sealed class InstanceClass : IInstanceClassInternal
{
int IInstanceClassInternal.OldValue { get; set; }
public int Value;
}
public static void Backup(InstanceClass ic)
{
((IInstanceClassInternal)ic).OldValue = ic.Value;
}
public static void Restore(InstanceClass ic)
{
ic.Value = ((IInstanceClassInternal)ic).OldValue;
}
}
It's obvious that you're trying to write Java in C# - the patterns, the coding style... That's probably a bad idea. Those static methods should probably be extension methods. The "hidden functionality in an object" doesn't quite sit with C#'s notion of OOP - your parent shouldn't have free access to your guts, it should only really have the same public interface everyone else has. After all, that's the whole point of LSP - such tight coupling is quite tricky for any extensibility. Why separate StaticClass from InstanceClass in the first place, if you want StaticClass to mess with InstanceClasses privates? Just make Backup and Restore public members of InstanceClass - or even a part of an interface (perhaps even through explicit implementation, if you want to "hide" it from users of InstanceClass).

You can use the internal access modifier, see https://msdn.microsoft.com/en-us/library/ms173121.aspx
Internal is only visible from inside the assembly
Example: https://dotnetfiddle.net/FNavfE

Have you tried to make it "internal"? It will be available in same dll but not external dll.
public class InstanceClass {
internal int oldValue;
public int Value;
}

Technically, you can use Reflection (if you insist on private field and a static class methods):
using System.Reflection;
...
public static void Backup(InstanceClass ic) {
if (null == ic)
throw new ArgumentNullException("ic");
ic.GetType()
.GetField("oldValue", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(ic, ic.Value);
}
public static void Restore(InstanceClass ic) {
if (null == ic)
throw new ArgumentNullException("ic");
ic.Value = (int) (ic.GetType()
.GetField("oldValue", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(ic));
}
however, a much better approach is to change access modifier from private to internal:
public class InstanceClass {
internal int oldValue;
public int Value;
}
Even better solution is to move both Backup and Restore methods into InstanceClass:
public class InstanceClass {
private int oldValue;
public int Value;
public void Backup() {
oldValue = Value;
}
public void Restore() {
Value = oldValue;
}
}

This field oldValue is an implementation detail of both StaticClass and InstanceClass. Lets make InstanceClass an implementation detail of StaticClass and export an interface StaticClass.IInstance to external clients:
public static class StaticClass {
public interface IInstance {
int Value { get; set; }
}
private class InstanceClass: IInstance {
public int oldValue;
public Value { get; set; }
}
// Static class becomes responsible for handing out `IInstance` objects
public static IInstance GetInstance() {
return new InstanceClass();
}
public static void Backup(IInstance i) {
if (i is InstanceClass ic) {
ic.oldValue = ic.Value;
}
else {
throw new InvallidOperationException("Can only Backup IInstance objects that were created by GetInstance");
}
}
public static void Restore(IInstance i) {
if (I is InstanceClass ic)
{
ic.Value = ic.oldValue;
}
else {
throw new InvallidOperationException("Can only Restore IInstance objects that were created by GetInstance");
}
}
This solution is similar to the one Luaan proposes. But instead of using an interface to export private data, it uses an interface to limit the publicly available data; to my opinion this is a cleaner design with less surprises.
It does change Value from a field to a property; so when you really need a field, this pattern does not work.
The static class in the example of OP makes it a bit awkward and having better solutions, but imagine this in a regular class, perhaps in a repository. Working on a repository, where observers should be notified when properties of items in the repository are set and not wanting the items to contain a reference to the repository or to the repositories observers, led me to searching for "method only accessible to container class?" which led me to this question.
I intend to solve it as follows:
public class Repo
{
public interface IItem
{
int Id { get; }
string MyProperty { get; }
}
private class Item
{
public int Id { get; }
public string MyProperty { get; private set; }
public bool TrySetMyProperty(string newValue)
{
if (!Equals(MyProperty, newValue) &&
IsPreconditionValid())
{
MyProperty = newValue;
return true;
}
else
{
return false;
}
IsPreconditionValid() => true;
}
}
public event EventHandler<EventArgs> OnChanged;
private readonly ConcurrentDictionary<int, Item> items = new ConcurrentDictionary<int, Item>();
public IItem GetOrCreateItemById(int id)
{
bool changed = false;
IItem result = items.GetOrAdd(int, CreateItem);
if (changed)
{
OnChanged?.Invoke(this, EventArgs.Empty);
}
return result;
IItem CreateItem(int key)
{
changed = true;
return new Item() { Id = key };
}
}
public bool TrySetItemMyProperty(int id, string newValue)
{
if (items.TryGet(id, out Item i))
{
if (i.TrySetMyProperty(newValue))
{
OnChanged?.Invoke(this, EventArgs.Empty);
return true;
}
}
return false;
}
}

Related

Inherit in generic classes C#

My brain is gonna to explode. :) So I would like to get help from you.
Please, think about my question like about just programmer puzzle. (Actually. perhaps it is very easy question for you, but not for me.)
It is needed to create array of objects. For example List where T is class. (I will describe Class T below). Also it is needed create “container” that will contain this array and some methods for work with this array. For example Add(), Remove(int IndexToRemove).
Class T must have field "Container", this way each elements of our array would be able to know where is it contained and has access its container's fields and methods. Notice, that in this case Class T should have type parameter. Indeed, it is not known beforehand which container's type is used.
Let us denote this class container as A and class element (class T) as AUnit.
Code:
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Add();
a.Units[0].SomeField +=100;
Console.ReadKey();
}
}
class A
{
public List<AUnit> Units;
public A()//ctor
{
Units = new List<AUnit>();
}
public void Add()
{
this.Units.Add(new AUnit(this));
}
}
class AUnit
{
public int SomeField;
public A Container;
public string Name { get; private set; }
public AUnit(A container)
{
this.SomeField = 43;
this.Container = container;
this.Name = "Default";
}
}
Public fields should be protected or private of course, but let think about this later.
You can ask “why we create public A Container field in AUnit”? We create field public string Name{get;private set;} (actually property but nevermind). And also we would like to be able to change value of this field for example method [Class AUnit] public bool Rename(string newName)();. The main idea of this method is changing Name field only that case if no one element in array (public List Units; ) has the same name like newName. But to achieve this, Rename method has to have access to all names that is currently used. And that is why we need Container field.
Code of extended version AUnit
class AUnit
{
public int SomeField;
public A Container;
public string Name { get; private set; }
public AUnit(A container)
{
this.SomeField = 43;
this.Container = container;
this.Name = "Default";
}
public bool Rename(String newName)
{
Boolean res = true;
foreach (AUnit unt in this.Container.Units)
{
if (unt.Name == newName)
{
res = false;
break;
}
}
if (res) this.Name = String.Copy(newName);
return res;
}
}
Ok. If you still read it let's continue. Now we need to create Class B and class BUnit which will be very similar like Class A and Class Aunit. And finally the main question of this puzzle is HOW WE CAN DO IT? Of course, I can CopyPaste and bit modify A and AUnit and create this code.
class B
{
public List<BUnit> Units; //Only Type Changing
public B()//ctor Name changing...
{
Units = new List<BUnit>();//Only Type Changing
}
public void Add()
{
this.Units.Add(new BUnit(this));//Only Type Changing
}
}
class BUnit
{
public int SomeField;
public B Container;//Only Type Changing
public string Name { get; private set; }
public A a; //NEW FIELD IS ADDED (just one)
public BUnit(B container) //Ctor Name and arguments type changing
{
this.SomeField = 43;
this.Container = container;
this.Name = "Default";
this.a=new A(); //New ROW (just one)
}
public bool Rename(String newName)
{
Boolean res = true;
foreach (BUnit unt in this.Container.Units) //Only Type Changing
{
if (unt.Name == newName)
{
res = false;
break;
}
}
if (res) this.Name = String.Copy(newName);
return res;
}
}
And I can to use this classes this way.
static void Main(string[] args)
{
B b = new B();
b.Add();
b.Units[0].a.Add();
b.Units[0].a.Units[0].SomeField += 100;
bool res= b.Units[0].a.Units[0].Rename("1");
res = b.Units[0].a.Units[0].Rename("1");
Console.ReadKey();
}
This construction is can be used to create “non-homogeneous trees”.
Help, I need somebody help, just no anybody…. [The Beatles]
I created B and BUnit using CopyPaste.
But how it can be done using “macro-definitions” or “Generic”, inherit or anything else in elegant style? (C# language)
I think that there is no reason to describe all my unsuccessful attempts and subquestions. Already topic is too long. : )
Thanks a lot if you still read it and understand what I would like to ask.
You need to implement a base type, lets call it UnitBase, with all common functionality. I'd structure your code the following way:
Create an interface for your container, this way you can change implementation to more performant solutions without modifying the elements you will be adding to the container.
public interface IContainer
{
Q Add<Q>() where Q : UnitBase, new();
IEnumerable<UnitBase> Units { get; }
}
Following the idea stated in 1, why not make the search logic belong to the container? It makes much more sense, as it will mostly depend on how the container is implemented:
public interface IContainer
{
Q Add<Q>() where Q : UnitBase, new();
IEnumerable<UnitBase> Units { get; }
bool Contains(string name);
}
A specific implementation of IContainer could be the following:
public class Container : IContainer
{
public Container()
{
list = new List<UnitBase>();
}
private List<UnitBase> list;
public Q Add<Q>() where Q: UnitBase, new()
{
var newItem = Activator.CreateInstance<Q>();
newItem.SetContainer(this);
list.Add(newItem);
return newItem;
}
public IEnumerable<UnitBase> Units => list.Select(i => i);
public bool Contains(string name) =>
Units.Any(unit => unit.Name == name);
}
Create a base class for your AUnit and BUnit types condensing all common functionality:
public abstract class UnitBase
{
protected UnitBase()
{
}
public IContainer Container { get; private set; }
public int SomeField;
public string Name { get; private set; }
public void SetContainer(IContainer container)
{
Container = container;
}
public bool Rename(String newName)
{
if (Container.Contains(newName))
return false;
this.Name = newName; //No need to use String.Copy
return true;
}
}
Implement your concrete types:
public class BUnit : UnitBase
{
public int SpecificBProperty { get; private set; }
public BUnit()
{
}
}
Shortcomings of this approach? Well, the container must be of type <UnitBase>, I've removed the generic type because it really wasn't doing much in this particular case as it would be invariant in the generic type.
Also, keep in mind that nothing in the type system avoids the following:
myContainer.Add<BUnit>();
myContainer.Add<AUnit>();
If having two different types in the same container is not an option then this whole set up kind of crumbles down. This issue was present in the previous solution too so its not something new, I simply forgot to point it out.
InBetween , I am very thankful to you for your advices. Actually I can't say that I understood your answer in full, but using your ideas I have done what I want.
Looks like my variant works well. However I would like to hear your (and everyone) opinions about code described below. The main goal of this structure is creating non-homogeneous trees. So could you estimate it from this side.
First of all. We need to create interfaces for both classes. We describe there all "cross-used" functions.
public interface IUnit<T>
{
string Name { get;}
void SetContainer(T t);
bool Rename(String newName);
}
public interface IContainer
{
bool IsNameBusy(String newName);
int Count { get; }
}
Next. Create Base for Unit Classes for future inheritance. We will use in this inheritors methods from Container Base so we need generic properties and IUnit interface.
class UnitBase<T> : IUnit<T> where T : IContainer
Unfortunately I don't know yet how to solve the problem with Constructor parameters. That is why I use method
SetContainer(T container).
Code:UnitBase
class UnitBase<T> : IUnit<T> where T : IContainer
{
protected T Container;
public string Name { get; private set; }
public UnitBase()
{
this.Name = "Default";
}
public void SetContainer(T container)
{
this.Container = container;
}
public bool Rename(String newName)
{
bool res = Container.IsNameBusy(newName);
if (!res) this.Name = String.Copy(newName);
return !res;
}
}
Next. Create ContainerBase
ContainerBase should:
1) has IContainer interface.
2)has information about what it will contain:
... where U : IUnit<C>, new()
3)and .... has information about what itself is. This information we need to pass as parameter to SetContainer() method.
Code ContainerBase:
class ContainerBase<U, C> : IContainer //U - Unit Class. C-Container Class
where U : IUnit<C>, new()
where C : ContainerBase<U, C>
{
protected List<U> Units;
public U this[int index] { get { return Units[index]; } }
public ContainerBase()//ctor
{
this.Units = new List<U>();
}
public void Add()
{
this.Units.Add(new U());
this.Units.Last().SetContainer(((C)this));//may be a bit strange but actualy this will have the same type as <C>
}
public bool IsNameBusy(String newName)
{
bool res = false;
foreach (var unt in this.Units)
{
if (unt.Name == newName)
{
res = true;
break;
}
}
return res;
}
public int Count { get { return this.Units.Count; } }
}
Cast ((TContainer)(this)) may be is a bit strange. But using ContainerBase we always should use NewInheritorContainer. So this cast is just do nothing…looks like...
Finally. This classes can be used like in this example.
class SheetContainer : ContainerBase<SheetUnit,SheetContainer> {public SheetContainer(){}}
class SheetUnit : UnitBase<SheetContainer>
{
public CellContainer Cells;
public PictureContainer Pictures;
public SheetUnit()
{
this.Cells = new CellContainer();
this.Pictures = new PictureContainer();
}
}
class CellContainer : ContainerBase<CellUnit, CellContainer> { public CellContainer() { } }
class CellUnit : UnitBase<CellContainer>
{
public string ValuePr;//Private Field
private const string ValuePrDefault = "Default";
public string Value//Property for Value
{
//All below are Just For Example.
get
{
return this.ValuePr;
}
set
{
if (String.IsNullOrEmpty(value))
{
this.ValuePr = ValuePrDefault;
}
else
{
this.ValuePr = String.Copy(value);
}
}
}
public CellUnit()
{
this.ValuePr = ValuePrDefault;
}
}
class PictureContainer : ContainerBase<PictureUnit, PictureContainer> { public PictureContainer() { } }
class PictureUnit : UnitBase<PictureContainer>
{
public int[,] Pixels{get;private set;}
public PictureUnit()
{
this.Pixels=new int[,]{{10,20,30},{11,12,13}};
}
public int GetSizeX()
{
return this.Pixels.GetLength(1);
}
public int GetSizeY()
{
return this.Pixels.GetLength(0);
}
public bool LoadFromFile(string path)
{
return false;
}
}
static void Main(string[] args)
{
SheetContainer Sheets = new SheetContainer();
Sheets.Add();
Sheets.Add();
Sheets.Add();
Sheets[0].Pictures.Add();
Sheets[1].Cells.Add();
Sheets[2].Pictures.Add();
Sheets[2].Cells.Add();
Sheets[2].Cells[0].Value = "FirstTest";
bool res= Sheets[0].Rename("First");//res=true
res=Sheets[2].Rename("First");//res =false
int res2 = Sheets.Count;
res2 = Sheets[2].Pictures[0].Pixels[1, 2];//13
res2 = Sheets[2].Pictures.Count;//1
res2 = Sheets[1].Pictures.Count;//0
res2 = Sheets[0].Pictures[0].GetSizeX();//3
Console.ReadKey();
}
Looks like it works like I want. But I didn’t test it full.
Let me say Thank you again, InBetween.

Polymorphism without using the virtual keyword

Obviously using virtual and override is the normal situation, but does this telecoms'ish example count?
public class Pipe
{
// whole bunch of protected member variables such as bandwidth, latency, download limit
// etc,
public int GetCost()
{
// work out cost based on above
}
}
public class BigFatPipe : Pipe
{
public BigFatPipe()
{
// sets up the member variables one way
}
}
public class CheapestPossiblePipe: Pipe
{
public CheapestPossiblePipe()
{
// sets up the member variables another way
}
}
then you might call
PrintPrice(new BigFatPipe())
PrintPrice(new CheapestPossiblePipe())
public void PrintPrice(Pipe pipe)
{
int a = pipe.GetCost();
....
}
You'll get two different answers. This isn't the most useful example but does it count?
This post here has a useful discussion of what exactly polymorphism is.
I think most definitions do not explicitly state that an object must have virtual functions to be polymorphic - so yes, I think your example counts.
Constructor overloading is a recognized method to implement static polymorphism. While this isn't really constructor overloading, it's close. So yes, I'd call it polymorphism.
This pattern does work, but introducing a bunch of classes will confuse the user uselessly: they will wonder what the classes do differently.
A few factories methods will do the same job and will be easier to understand and maintain:
public class Pipe
{
// whole bunch of private member variables such as bandwidth, latency, download limit
// etc,
public int GetCost()
{
// work out cost based on above
}
public static Pipe MakeBigFatPipe()
{
var result = new Pipe();
// sets up the member variables one way
return result;
}
public static Pipe MakeCheapestPossiblePipe()
{
var result = new Pipe();
// sets up the member variables another way
return result;
}
}
If I were you I would use folowing approach:
public interface IGetCost
{
int GetCost();
}
public class Pipe : IGetCost
{
public int GetCost(){}
}
public class BigFatPipe : IGetCost
{
//aggregation
private readonly Pipe _pipe;
public BigFatPipe(Pipe pipe)
{
_pipe = pipe;
}
public int GetCost() { }
}
public class CheapestPossiblePipe : IGetCost
{
private readonly Pipe _pipe;
public CheapestPossiblePipe(Pipe pipe)
{
_pipe = pipe;
}
public int GetCost() { }
}
public static void PrintPrice(IGetCost obj)
{
int cost = obj.GetCost();
Console.WriteLine(cost);
}
static void Main(string[] args)
{
IGetCost p;
p = new Pipe();
PrintPrice(p);
p = new BigFatPipe();
PrintPrice(p);
p = new CheapestPossiblePipe();
PrintPrice(p);
}
I also need to say that there're two different things - polymorphism and overloading
polymorphism
public class foo
{
public virtual void foo1{/*....*/}
}
public class fooA : foo
{
public override void foo1{/*....*/}
}
public class fooB : foo
{
public new void foo1{/*....*/}
}
public class fooC : foo
{
//new is the default modifier
public void foo1{/*....*/}
}
overloading
public class foo{
public int foo1{/*....*/}
public int foo1(int a){/*....*/}
public int foo1(string a){/*....*/}
public int foo1(int a, string b){/*....*/}
}

How to write extension method that work with base class

Idea is to have extension method that extend my functionality.
So instead of having something like this:
return Add(Add(storage.GetFirst(), 3), 7);
I want have something like this:
return storage.GetFirst().Add(3).Add(7);
Problem with extension methods is that they have to be static in static class.
This is simplify example of what I want to do.
public class Storage
{
public int GetFirst()
{
return 100;
}
public int GetAll(int x, int y)
{
// ...
return x + y;
}
}
public abstract class MyBase
{
protected Storage storage;
protected MyBase()
{
storage = new Storage();
}
public int Add(int what, int howMuch)
{
return storage.GetAll(what, howMuch);
}
}
public class MyClass : MyBase
{
public int method1()
{
return Add(Add(storage.GetFirst(), 3), 7);
//I want have something like this:
// return storage.GetFirst().Add(3).Add(7);
}
}
Off course classes Storage, MyBase and MyClass must not be static. Logic is simplify to have clean and simple example so relation between classes must stay same.
What I want to do is to make Add method to be extension method, but leave everything else "more less same".
Is this possible to do and how?
An alternative solution would be to make your Storage class actually store something:
public class Storage
{
private int currentValue;
public Storage GetFirst()
{
this.currentValue = 100;
return this;
}
public Storage Add(int toAdd)
{
this.currentValue += toAdd;
return this;
}
public int GetResult()
{
return this.currentValue;
}
}
This way your call would be:
int result = new Storage().GetFirst().Add(3).Add(5).GetResult();
Have one static class for extensions and use something like:
internal static T Map<T> (this int source, Func<int, int, T> function, int extraParam) {
function (source, extraParam);
}
Then you can make your add method something like:
storage.GetFirst ().Map (Add, 3).Map (Add, 7);
Without modifying any of your code, it is possible to achieve what you're trying to do. But your current design makes it hard to do. You should have some storage in Storage class. There is no storage in Storage class despite of its name.
public class StorageValue
{
public StorageValue(Storage storage)
{
this.Storage = storage;
}
public StorageValue(Storage storage, int value)
{
this.Storage = storage;
this.Value = value;
}
public Storage Storage { get; private set; }
public int Value { get; private set; }
public StorageValue GetFirst()
{
return new StorageValue(Storage, Storage.GetFirst());
}
public StorageValue Add(int value)
{
return new StorageValue(Storage, Storage.GetAll(Value, value));
}
public int GetValue()
{
return Value;
}
}
public static class StorageExtensions
{
public static StorageValue ToStorageValue(this Storage storage)
{
return new StorageValue(storage);
}
}
Which these couple of classes, you can call the methods like this
public class MyClass : MyBase
{
public int method1()
{
return storage
.ToStorageValue()
.GetFirst()
.Add(3)
.Add(7)
.GetValue();
}
}
If you want Add, GetFirst to be the extension methods, you may do it now with StorageValue class. But it makes more sense to be in StorageValue class itself.
That said, # Manuel Zelenka's answer is similar to mine which looks better. You may adapt any of them.

Initialization of static fields in C# generic types

I understood from this answer that C# static field initializers "are executed... prior to the first use of a static field of that class," but that still produces results I didn't expect, at least with generic types.
Coming from the Java world, I was missing my rich enums, and I thought with C#'s more serious generics that I ought to be able to replicate them with a minimum of boilerplate. Here (stripped of some details, like comparability) is what I came up with:
public class AbstractEnum<T> where T : AbstractEnum<T>
{
static readonly IDictionary<String, T> nameRegistry = new Dictionary<String, T>();
readonly String name;
protected AbstractEnum (String name)
{
this.name = name;
nameRegistry[name] = (T) this;
}
public String Name {
get {
return name;
}
}
public static T ValueOf(String name) {
return nameRegistry[name];
}
public static IEnumerable<T> Values {
get {
return nameRegistry.Values;
}
}
}
And some example subclasses:
public class SomeEnum : AbstractEnum<SomeEnum> {
public static readonly SomeEnum V1 = new SomeEnum("V1");
public static readonly SomeEnum V2 = new SomeEnum("V2");
SomeEnum(String name) : base(name) {
}
}
public class OtherEnum : AbstractEnum<OtherEnum> {
public static readonly OtherEnum V1 = new OtherEnum("V1");
public static readonly OtherEnum V2 = new OtherEnum("V2");
OtherEnum(String name) : base(name) {
}
}
This looks good and more or less does the trick... except that, following the letter of the spec, the actual instances (SomeEnum.V1, OtherEnum.V1 etc.) don't get initialized unless at least one of them is referred to explicitly. Static fields/methods in the base class don't count. So, for instance, the following:
Console.WriteLine("Count: {0}", SomeEnum.Values.Count());
foreach (SomeEnum e in SomeEnum.Values) {
Console.WriteLine(e.Name);
}
writes Count: 0, but if I add the following line --
Console.WriteLine("SomeEnum.V1: " + SomeEnum.V1.Name);
-- even after the above, I get:
Count: 2
V1
V2
(Note, by the way, that initializing the instances in a static constructor makes no difference.)
Now, I can fix this by marking nameRegistry as protected and pushing Values and ValueOf down into the subclasses, but I was hoping to keep all the complexity in the superclass and keep the boilerplate to a minimum. Can anyone whose C#-fu is superior to mine come up with a trick for making the subclass instances "self-executing"?
Note: FWIW, this is in Mono, on Mac OS. YM in MS .NET, on Windows, MV.
ETA: For monoglot C# developers (or even polyglot developers whose experience is limited to languages starting with 'C') wondering WTF I'm trying to do: this. C# enums take care of the type safety issue, but they're still missing everything else.
I came up with this - not entirely pleasing, but does do the job:
public static IEnumerable<T> Values
{
get
{
if (nameRegistry.Count > 0)
{
return nameRegistry.Values;
}
var aField = typeof (T).GetFields(
BindingFlags.Public | BindingFlags.Static)
.FirstOrDefault();
if (aField != null)
aField.GetValue(null);
return nameRegistry.Values;
}
}
EDIT Here's a slightly different version that should address VinayC's concerns in the comments. The problem was this: thread A calls Values(). While the static constructor of SomeEnum is running, after it's added V1 but before it adds V2, thread B calls values. In the code as originally written, it would be handed an IEnumerable that might only yield V1. So you could get incorrect results from Values() if a second thread calls during the very first call to Values() for any particular type.
The version below uses a boolean flag rather than relying on a non-zero count in nameRegistry. In this version it is still possible that the reflection code to run more than once, but no longer possible to get wrong answers from Values(), since by the time the reflection code completes, the nameRegistry is guaranteed to be fully initialized.
private static bool _initialized;
public static IEnumerable<T> Values
{
get
{
if (_initialized)
{
return nameRegistry.Values;
}
var aField = typeof(T).GetFields(
BindingFlags.Public | BindingFlags.Static)
.FirstOrDefault();
if (aField != null)
aField.GetValue(null);
_initialized = true;
return nameRegistry.Values;
}
}
Admittedly, I don't know what RichEnums are, but does this C# not do what you want?
public enum SomeEnum
{
V1,
V2
}
class Program
{
static void Main(string[] args)
{
var values = Enum.GetValues(typeof (SomeEnum));
Console.WriteLine("Count: {0}", values.Length);
foreach (SomeEnum e in values)
{
Console.WriteLine(e);
}
}
}
How about:
public class BaseRichEnum
{
public static InitializeAll()
{
foreach (Type t in Assembly.GetExecutingAssembly().GetTypes())
{
if (t.IsClass && !t.IsAbstract && typeof (BaseRichEnum).IsAssignableFrom(t))
{
t.GetMethod("Initialize").Invoke(null, null); //might want to use flags on GetMethod
}
}
}
}
public class AbstractEnum<T> : BaseRichEnum where T : AbstractEnum<T>
{
static readonly IDictionary<String, T> nameRegistry = new Dictionary<String, T>();
readonly String name;
protected AbstractEnum (String name)
{
this.name = name;
nameRegistry[name] = (T) this;
}
public String Name {
get {
return name;
}
}
public static T ValueOf(String name) {
return nameRegistry[name];
}
public static IEnumerable<T> Values {
get {
return nameRegistry.Values;
}
}
}
And then:
public class SomeEnum : AbstractEnum<SomeEnum>
{
public static readonly SomeEnum V1;
public static readonly SomeEnum V2;
public static void Initialize()
{
V1 = new SomeEnum("V1");
V2 = new SomeEnum("V2");
}
SomeEnum(String name) : base(name) {
}
}
Then you have to call BaseRichEnum.InitializeAll() in application startup code. I think it's better to impose this simple requirement on clients, thereby making visible the mechanism, than to expect future maintainers to grasp the subtleties of static-time initialization.
I don't like below solution as such but...
public class AbstractEnum<T> where T : AbstractEnum<T>
{
...
private static IEnumerable<T> ValuesInternal {
get {
return nameRegistry.Values;
}
}
public IEnumerable<T> Values {
get {
return ValuesInternal;
}
}
}
You have to use like SomeEnum.V1.Values - I know it sucks!
Yet another alternative that would involve some work is
public class AbstractEnum<T> where T : AbstractEnum<T>
{
...
protected static IEnumerable<T> ValuesInternal {
get {
return nameRegistry.Values;
}
}
}
public class SomeEnum : AbstractEnum<SomeEnum> {
...
public static IEnumerable<SomeEnum> Values
{
get
{
return ValuesInternal;
}
}
}
I would go with the second option.

Making a superclass have a static variable that's different for each subclass in c#

Without any code in the subclasses, I'd like an abstract class to have a different copy of a static variable for each subclass. In C#
abstract class ClassA
{
static string theValue;
// just to demonstrate
public string GetValue()
{
return theValue;
}
...
}
class ClassB : ClassA { }
class ClassC : ClassA { }
and (for example):
(new ClassB()).GetValue(); // returns "Banana"
(new ClassC()).GetValue(); // returns "Coconut"
My current solution is this:
abstract class ClassA
{
static Dictionary<Type, string> theValue;
public string GetValue()
{
return theValue[this.GetType()];
}
...
}
While this works fine, I'm wondering if there's a more elegant or built-in way of doing this?
This is similar to Can I have different copies of a static variable for each different type of inheriting class, but I have no control over the subclasses
There is a more elegant way. You can exploit the fact that statics in a generic base class are different for each derived class of a different type
public abstract class BaseClass<T> where T : class
{
public static int x = 6;
public int MyProperty { get => x; set => x = value; }
}
For each child class, the static int x will be unique for each unique T
Lets derive two child classes, and we use the name of the child class as the generic T in the base class.
public class ChildA: BaseClass<ChildA>
{
}
public class ChildB : BaseClass<ChildB>
{
}
Now the static MyProperty is unique for both ChildA and ChildB
var TA = new ChildA();
TA.MyProperty = 8;
var TB = new ChildB();
TB.MyProperty = 4;
While this works fine, I'm wondering if there's a more elegant or built-in way of doing this?
There isn't really a built-in way of doing this, as you're kind of violating basic OO principles here. Your base class should have no knowledge of subclasses in traditional object oriented theory.
That being said, if you must do this, your implementation is probably about as good as you're going to get, unless you can add some other info to the subclasses directly. If you need to control this, and you can't change subclasses, this will probably be your best approach.
This is a little different than what you're asking for, but perhaps accomplishes the same thing.
class Program
{
static void Main(string[] args)
{
Console.WriteLine((new B()).theValue);
Console.WriteLine((new C()).theValue);
Console.ReadKey();
}
}
public abstract class A
{
public readonly string theValue;
protected A(string s)
{
theValue = s;
}
}
public class B : A
{
public B(): base("Banana")
{
}
}
public class C : A
{
public C(): base("Coconut")
{
}
}
There's an alternative solution which might or might not be better than yours, depending on the use case:
abstract class ClassA
{
private static class InternalClass<T> {
public static string Value;
}
public string GetValue()
{
return (string)typeof(InternalClass<>)
.MakeGenericType(GetType())
.GetField("Value", BindingFlags.Public | BindingFlags.Static)
.GetValue(null);
}
}
This approach is used in EqualityComparer<T>.Default. Of course, it's not used for this problem. You should really consider making GetValue abstract and override it in each derived class.
What about this?
class Base {
protected static SomeObjectType myVariable;
protected void doSomething()
{
Console.WriteLine( myVariable.SomeProperty );
}
}
class AAA : Base
{
static AAA()
{
myVariable = new SomeObjectType();
myVariable.SomeProperty = "A";
}
}
class BBB : Base
{
static BBB()
{
myVariable = new SomeObjectType();
myVariable.SomeProperty = "B";
}
}
It works for me.
Would be even nicer with Interface.
Simple solution: just use word "new".
public abstract class AbstractClass
{
public static int Variable;
}
public class RealizationA : AbstractClass
{
public new static int Variable;
}
public class RealizationB : AbstractClass
{
public new static int Variable;
}
And the result:
AbstractClass.Variable = 1;
RealizationA.Variable = 2;
RealizationB.Variable = 3;
Console.WriteLine(AbstractClass.Variable); //1
Console.WriteLine(RealizationA.Variable); //2
Console.WriteLine(RealizationB.Variable); //3
or you can use property:
//in abstract class
public static int Variable {get; set;}
//in child class
public static new int Variable {get; set;}
or function (but remember to add "new" to both variable and function):
//in abstract class
protected static int Variable;
public static int GetVariable() { return Variable; }
public static void SetVariable(int v) { Variable = v; }
//in child class
protected new static int Variable;
public static new int GetVariable() { return Variable; }
public static new void SetVariable(int v) { Variable = v; }
or you can use private variables (you don't need to use "new") with functions to get and set:
//in abstract class
private static int Variable;
//get and set methods
//in child class
private static int Variable;
//get and set methods

Categories