C# casting and inheritance - c#

I have an object that I pass around a lot.
I need to add a piece of data to it and cannot modify the base class
So I have
static OriginalThing GetNewThing()
{
return new OriginalThing();
}
Now i want to add my piece of data
class EnhancedThing : OriginalThing
{
string name;
static EnhancedThing GetNewThing(string name)
{
EnhancedThing ething = new OriginalThing(); <---doesnt work even if i cast it
ething.Name = name;
}
}
How do I do this?

You can't assign an OriginalThing to a NewThing because it simply is not a NewThing. The other way around works fine because a NewThing is capable of everything an OriginalThing is, but the reverse is not true.
Just create an instance of EnhancedThing, assign the name, and return it. You can treat the EnhancedThing as if it were an OriginalThing because it is an OriginalThing.
class EnhancedThing : OriginalThing
{
public string Name { get; private set; }
static EnhancedThing GetNewThing(string name)
{
EnhanedThing thing = new EnhancedThing();
thing.Name = name;
return thing;
}
}
// ...
OriginalThing foo = EnhancedThing.GetNewThing( "someName" );
Also realize that doesn't buy you much as name is currently a private member variable (in your example), and you won't be able to access any additional functionality of NewThing objects unless you treat them as NewThings (as opposed to OriginalThings, but you can pass them around as OriginalThings if needed)

You need to do this:
EnhancedThing ething = new EnhancedThing();

This is because an OriginalThing is not an EnhancedThing, but an EnhancedThing is an OriginalThing.
One thing you could do is have a constructor for EnhancedThing that takes an OriginalThing and copies over the members that apply.
class EnhancedThing : OriginalThing
{
public EnhancedThing()
{
// default constructor
}
public EnhancedThing( OriginalThing src )
{
// copy over the significant items
}
}

If the other class is sealed you can use encapsulation in your new class, and then modify/extend the API. You can then define a implicit cast from one object to the other and use these types interchangeably without casting.
Whether this is suitable in your case comes down to what you intend to do, and what you are trying to achieve but it's a valuable technique. It's more useful for hiding some/all members of the original and redefining an API.
// no need to cast
EnhancedThing thing = new OriginalThing();
var result = thing.NewMethod();
// again no need to cast, treat as original when passing around
OriginalThing original = thing;
public class EnhancedThing
{
private readonly OriginalThing originalThing;
public static implicit operator OriginalThing(EnhancedThing enhancedThing)
{
return enhancedThing.originalThing;
}
public static implicit operator EnhancedThing(OriginalThing originalThing)
{
return new EnhancedThing(originalThing);
}
private EnhancedThing(OriginalThing originalThing)
{
this.originalThing = originalThing;
}
public string OriginalMethod()
{
return originalThing.OriginalMethod();
}
public string NewMethod()
{
var value = originalThing.OriginalMethod();
// extra processing ...
return value;
}
}
This technique is used extensively in Sitecore to provide different data type Models from a common base implementation. One caveat if you intend to add a new data field, it will be lost on upcast.

Related

Why is it impossible to cast to a derived type [duplicate]

Is it possible to assign a base class object to a derived class reference with an explicit typecast in C#?.
I have tried it and it creates a run-time error.
No. A reference to a derived class must actually refer to an instance of the derived class (or null). Otherwise how would you expect it to behave?
For example:
object o = new object();
string s = (string) o;
int i = s.Length; // What can this sensibly do?
If you want to be able to convert an instance of the base type to the derived type, I suggest you write a method to create an appropriate derived type instance. Or look at your inheritance tree again and try to redesign so that you don't need to do this in the first place.
No, that's not possible since assigning it to a derived class reference would be like saying "Base class is a fully capable substitute for derived class, it can do everything the derived class can do", which is not true since derived classes in general offer more functionality than their base class (at least, that's the idea behind inheritance).
You could write a constructor in the derived class taking a base class object as parameter, copying the values.
Something like this:
public class Base {
public int Data;
public void DoStuff() {
// Do stuff with data
}
}
public class Derived : Base {
public int OtherData;
public Derived(Base b) {
this.Data = b.Data;
OtherData = 0; // default value
}
public void DoOtherStuff() {
// Do some other stuff
}
}
In that case you would copy the base object and get a fully functional derived class object with default values for derived members. This way you can also avoid the problem pointed out by Jon Skeet:
Base b = new Base();//base class
Derived d = new Derived();//derived class
b.DoStuff(); // OK
d.DoStuff(); // Also OK
b.DoOtherStuff(); // Won't work!
d.DoOtherStuff(); // OK
d = new Derived(b); // Copy construct a Derived with values of b
d.DoOtherStuff(); // Now works!
Solution with JsonConvert (instead of typecast)
Today i faced the same issue and i found a simple and quick solution to the problem using JsonConvert.
var base = new BaseClass();
var json = JsonConvert.SerializeObject(base);
DerivedClass derived = JsonConvert.DeserializeObject<DerivedClass>(json);
I had this problem and solved it by adding a method that takes a type parameter and converts the current object into that type.
public TA As<TA>() where TA : Base
{
var type = typeof (TA);
var instance = Activator.CreateInstance(type);
PropertyInfo[] properties = type.GetProperties();
foreach (var property in properties)
{
property.SetValue(instance, property.GetValue(this, null), null);
}
return (TA)instance;
}
That means that you can use it in you code like this:
var base = new Base();
base.Data = 1;
var derived = base.As<Derived>();
Console.Write(derived.Data); // Would output 1
As many others have answered, No.
I use the following code on those unfortunate occasions when I need to use a base type as a derived type. Yes it is a violation of the Liskov Substitution Principle (LSP) and yes most of the time we favor composition over inheritance. Props to Markus Knappen Johansson whose original answer this is based upon.
This code in the base class:
public T As<T>()
{
var type = typeof(T);
var instance = Activator.CreateInstance(type);
if (type.BaseType != null)
{
var properties = type.BaseType.GetProperties();
foreach (var property in properties)
if (property.CanWrite)
property.SetValue(instance, property.GetValue(this, null), null);
}
return (T) instance;
}
Allows:
derivedObject = baseObect.As<derivedType>()
Since it uses reflection, it is "expensive". Use accordingly.
No it is not possible, hence your runtime error.
But you can assign an instance of a derived class to a variable of base class type.
As everyone here said, that's not possible directly.
The method I prefer and is rather clean, is to use an Object Mapper like AutoMapper.
It will do the task of copying properties from one instance to another (Not necessarily the same type) automatically.
In c# 9.0 you can try to use records for this. They have default copy constructor that copy all fields - no need to use reflection / constructor with all fields.
public record BaseR
{
public string Prop1 { get; set; }
}
public record DerivedR : BaseR
{
public DerivedR(BaseR baseR) : base(baseR) { }
public string Prop2 { get; set; }
}
var baseR = new BaseR { Prop1 = "base prob" };
var derivedR = new DerivedR(baseR) { Prop2 = "new prop" };
Not in the Traditional Sense... Convert to Json, then to your object, and boom, done! Jesse above had the answer posted first, but didn't use these extension methods which make the process so much easier. Create a couple of extension methods:
public static string ConvertToJson<T>(this T obj)
{
return JsonConvert.SerializeObject(obj);
}
public static T ConvertToObject<T>(this string json)
{
if (string.IsNullOrEmpty(json))
{
return Activator.CreateInstance<T>();
}
return JsonConvert.DeserializeObject<T>(json);
}
Put them in your toolbox forever, then you can always do this:
var derivedClass = baseClass.ConvertToJson().ConvertToObject<derivedClass>();
Ah, the power of JSON.
There are a couple of gotchas with this approach: We really are creating a new object, not casting, which may or may not matter. Private fields will not be transferred, constructors with parameters won't be called, etc. It is possible that some child json won't be assigned. Streams are not innately handled by JsonConvert. However, if our class doesn't rely on private fields and constructors, this is a very effective method of moving data from class to class without mapping and calling constructors, which is the main reason why we want to cast in the first place.
Expanding on #ybo's answer - it isn't possible because the instance you have of the base class isn't actually an instance of the derived class. It only knows about the members of the base class, and doesn't know anything about those of the derived class.
The reason that you can cast an instance of the derived class to an instance of the base class is because the derived class actually already is an instance of the base class, since it has those members already. The opposite cannot be said.
You can cast a variable that is typed as the base-class to the type of a derived class; however, by necessity this will do a runtime check, to see if the actual object involved is of the correct type.
Once created, the type of an object cannot be changed (not least, it might not be the same size). You can, however, convert an instance, creating a new instance of the second type - but you need to write the conversion code manually.
You have to use an object cloner/copier that will assign all the properties one by one.
Doing this by hand is inefficient and not future-proof. But serializing & deserializing to JSON and back is not the best solution, it is slow and very memory inefficient.
However, using AutoMapper is fast. PropMapper is even faster.
PS. Disclosure: I am a contributor at PropMapper open source project.
No, it is not possible.
Consider a scenario where an ACBus is a derived class of base class Bus. ACBus has features like TurnOnAC and TurnOffAC which operate on a field named ACState. TurnOnAC sets ACState to on and TurnOffAC sets ACState to off. If you try to use TurnOnAC and TurnOffAC features on Bus, it makes no sense.
class Program
{
static void Main(string[] args)
{
a a1 = new b();
a1.print();
}
}
class a
{
public a()
{
Console.WriteLine("base class object initiated");
}
public void print()
{
Console.WriteLine("base");
}
}
class b:a
{
public b()
{
Console.WriteLine("child class object");
}
public void print1()
{
Console.WriteLine("derived");
}
}
}
when we create a child class object,the base class object is auto initiated so base class reference variable can point to child class object.
but not vice versa because a child class reference variable can not point to base class object because no child class object is created.
and also notice that base class reference variable can only call base class member.
There actually IS a way to do this. Think about how you might use Newtonsoft JSON to deserialize an object from json. It will (or at least can) ignore missing elements and populate all the elements that it does know about.
So here's how I did it. A small code sample will follow my explanation.
Create an instance of your object from the base class and populate it accordingly.
Using the "jsonconvert" class of Newtonsoft json, serialize that object into a json string.
Now create your sub class object by deserializing with the json string created in step 2. This will create an instance of your sub class with all the properties of the base class.
This works like a charm! So.. when is this useful? Some people asked when this would make sense and suggested changing the OP's schema to accommodate the fact that you can't natively do this with class inheritance (in .Net).
In my case, I have a settings class that contains all the "base" settings for a service. Specific services have more options and those come from a different DB table, so those classes inherit the base class. They all have a different set of options. So when retrieving the data for a service, it's much easier to FIRST populate the values using an instance of the base object. One method to do this with a single DB query. Right after that, I create the sub class object using the method outlined above. I then make a second query and populate all the dynamic values on the sub class object.
The final output is a derived class with all the options set. Repeating this for additional new sub classes takes just a few lines of code. It's simple, and it uses a very tried and tested package (Newtonsoft) to make the magic work.
This example code is vb.Net, but you can easily convert to c#.
' First, create the base settings object.
Dim basePMSettngs As gtmaPayMethodSettings = gtmaPayments.getBasePayMethodSetting(payTypeId, account_id)
Dim basePMSettingsJson As String = JsonConvert.SerializeObject(basePMSettngs, Formatting.Indented)
' Create a pmSettings object of this specific type of payment and inherit from the base class object
Dim pmSettings As gtmaPayMethodAimACHSettings = JsonConvert.DeserializeObject(Of gtmaPayMethodAimACHSettings)(basePMSettingsJson)
You can use an Extention:
public static void CopyOnlyEqualProperties<T>(this T objDest, object objSource) where T : class
{
foreach (PropertyInfo propInfo in typeof(T).GetProperties())
if (objSource.GetType().GetProperties().Any(z => z.Name == propInfo.Name && z.GetType() == propInfo.GetType()))
propInfo.SetValue(objDest, objSource.GetType().GetProperties().First(z => z.Name == propInfo.Name && z.GetType() == propInfo.GetType()).GetValue(objSource));
}
In Code:
public class BaseClass
{
public string test{ get; set;}
}
public Derived : BaseClass
{
//Some properies
}
public void CopyProps()
{
BaseClass baseCl =new BaseClass();
baseCl.test="Hello";
Derived drv=new Derived();
drv.CopyOnlyEqualProperties(baseCl);
//Should return Hello to the console now in derived class.
Console.WriteLine(drv.test);
}
Might not be relevent, but I was able to run code on a derived object given its base. It's definitely more hacky than I'd like, but it works:
public static T Cast<T>(object obj)
{
return (T)obj;
}
...
//Invoke parent object's json function
MethodInfo castMethod = this.GetType().GetMethod("Cast").MakeGenericMethod(baseObj.GetType());
object castedObject = castMethod.Invoke(null, new object[] { baseObj });
MethodInfo jsonMethod = baseObj.GetType ().GetMethod ("ToJSON");
return (string)jsonMethod.Invoke (castedObject,null);
You can do this using generic.
public class BaseClass
{
public int A { get; set; }
public int B { get; set; }
private T ConvertTo<T>() where T : BaseClass, new()
{
return new T
{
A = A,
B = B
}
}
public DerivedClass1 ConvertToDerivedClass1()
{
return ConvertTo<DerivedClass1>();
}
public DerivedClass2 ConvertToDerivedClass2()
{
return ConvertTo<DerivedClass2>();
}
}
public class DerivedClass1 : BaseClass
{
public int C { get; set; }
}
public class DerivedClass2 : BaseClass
{
public int D { get; set; }
}
You get three benefits using this approach.
You are not duplicating the code
You are not using reflection (which is slow)
All of your conversions are in one place
I know this is old but I've used this successfully for quite a while.
private void PopulateDerivedFromBase<TB,TD>(TB baseclass,TD derivedclass)
{
//get our baseclass properties
var bprops = baseclass.GetType().GetProperties();
foreach (var bprop in bprops)
{
//get the corresponding property in the derived class
var dprop = derivedclass.GetType().GetProperty(bprop.Name);
//if the derived property exists and it's writable, set the value
if (dprop != null && dprop.CanWrite)
dprop.SetValue(derivedclass,bprop.GetValue(baseclass, null),null);
}
}
I combined some portions of the previous answers (thanks to those authors) and put together a simple static class with two methods that we're using.
Yes, it's simple, no it doesn't cover all scenarios, yes it could be expanded and made better, no it's not perfect, yes it could possibly be made more efficient, no it's not the greatest thing since sliced bread, yes there are full-on robust nuget package object mappers out there that are way better for heavy use, etc etc, yada yada - but it works for our basic needs though :)
And of course it will try to map values from any object to any object, derived or not (only the public properties that are named the same of course - ignores the rest).
USAGE:
SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };
// creates new object of type "RealPerson" and assigns any matching property
// values from the puppet object
// (this method requires that "RealPerson" have a parameterless constructor )
RealPerson person = ObjectMapper.MapToNewObject<RealPerson>(puppet);
// OR
// create the person object on our own
// (so RealPerson can have any constructor type that it wants)
SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };
RealPerson person = new RealPerson("tall") {Name = "Steve"};
// maps and overwrites any matching property values from
// the puppet object to the person object so now our person's age will get set to 5 and
// the name "Steve" will get overwritten with "Elmo" in this example
ObjectMapper.MapToExistingObject(puppet, person);
STATIC UTILITY CLASS:
public static class ObjectMapper
{
// the target object is created on the fly and the target type
// must have a parameterless constructor (either compiler-generated or explicit)
public static Ttarget MapToNewObject<Ttarget>(object sourceobject) where Ttarget : new()
{
// create an instance of the target class
Ttarget targetobject = (Ttarget)Activator.CreateInstance(typeof(Ttarget));
// map the source properties to the target object
MapToExistingObject(sourceobject, targetobject);
return targetobject;
}
// the target object is created beforehand and passed in
public static void MapToExistingObject(object sourceobject, object targetobject)
{
// get the list of properties available in source class
var sourceproperties = sourceobject.GetType().GetProperties().ToList();
// loop through source object properties
sourceproperties.ForEach(sourceproperty => {
var targetProp = targetobject.GetType().GetProperty(sourceproperty.Name);
// check whether that property is present in target class and is writeable
if (targetProp != null && targetProp.CanWrite)
{
// if present get the value and map it
var value = sourceobject.GetType().GetProperty(sourceproperty.Name).GetValue(sourceobject, null);
targetobject.GetType().GetProperty(sourceproperty.Name).SetValue(targetobject, value, null);
}
});
}
}
You can use a copy constructor that immediately invokes the instance constructor, or if your instance constructor does more than assignments have the copy constructor assign the incoming values to the instance.
class Person
{
// Copy constructor
public Person(Person previousPerson)
{
Name = previousPerson.Name;
Age = previousPerson.Age;
}
// Copy constructor calls the instance constructor.
public Person(Person previousPerson)
: this(previousPerson.Name, previousPerson.Age)
{
}
// Instance constructor.
public Person(string name, int age)
{
Name = name;
Age = age;
}
public int Age { get; set; }
public string Name { get; set; }
}
Referenced the Microsoft C# Documentation under Constructor for this example having had this issue in the past.
With regarding #MarkusKnappenJohansson answer and below comments we can change his code extending extension function :) so it may update an existing deriving class instance via this code :
public static TDerived As<TDerived>(this Base baseInstance, TDerived updateDerivedInstance = null) where TDerived : Base, new()
{
Type baseType = typeof(Base);
Type derivedType = typeof(TDerived);
PropertyInfo[] properties = baseType.GetProperties();
object instanceDerived = null;
if (updateDerivedInstance == null)
{
instanceDerived = Activator.CreateInstance(derivedType);
}
else
{
instanceDerived = (object)(updateDerivedInstance);
}
foreach (PropertyInfo property in properties)
{
if (property.CanWrite)
{
property.SetValue(instanceDerived, property.GetValue(baseInstance, null), null);
}
}
return (TDerived)instanceDerived;
}
Usage for getting new derived Instance is var base = new Base(); base.Data = 1; var derived = base.As<Derived>(); Console.Write(derived.Data); // Would output 1
Usage for updating existing derived Instance is var derived = new Derived(); var base = new Base(); base.Data = 1; var derivedUpdated = base.As<Derived>(derived); Console.Write(derivedUpdated.Data); // Would output 1
Another solution is to add extension method like so:
public static void CopyProperties(this object destinationObject, object sourceObject, bool overwriteAll = true)
{
try
{
if (sourceObject != null)
{
PropertyInfo[] sourceProps = sourceObject.GetType().GetProperties();
List<string> sourcePropNames = sourceProps.Select(p => p.Name).ToList();
foreach (PropertyInfo pi in destinationObject.GetType().GetProperties())
{
if (sourcePropNames.Contains(pi.Name))
{
PropertyInfo sourceProp = sourceProps.First(srcProp => srcProp.Name == pi.Name);
if (sourceProp.PropertyType == pi.PropertyType)
if (overwriteAll || pi.GetValue(destinationObject, null) == null)
{
pi.SetValue(destinationObject, sourceProp.GetValue(sourceObject, null), null);
}
}
}
}
}
catch (ApplicationException ex)
{
throw;
}
}
then have a constructor in each derived class that accepts base class:
public class DerivedClass: BaseClass
{
public DerivedClass(BaseClass baseModel)
{
this.CopyProperties(baseModel);
}
}
It will also optionally overwrite destination properties if already set (not null) or not.
Is it possible to assign a base class object to a derived class reference with an explicit typecast in C#?.
Not only explicit, but also implicit conversions are possible.
C# language doesn't permit such conversion operators, but you can still write them using pure C# and they work. Note that the class which defines the implicit conversion operator (Derived) and the class which uses the operator (Program) must be defined in separate assemblies (e.g. the Derived class is in a library.dll which is referenced by program.exe containing the Program class).
//In library.dll:
public class Base { }
public class Derived {
[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Implicit(Base a) {
return new Derived(a); //Write some Base -> Derived conversion code here
}
[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Explicit(Base a) {
return new Derived(a); //Write some Base -> Derived conversion code here
}
}
//In program.exe:
class Program {
static void Main(string[] args) {
Derived z = new Base(); //Visual Studio can show squiggles here, but it compiles just fine.
}
}
When you reference the library using the Project Reference in Visual Studio, VS shows squiggles when you use the implicit conversion, but it compiles just fine. If you just reference the library.dll, there are no squiggles.
How about:
public static T As<T>(this object obj)
{
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(obj));
}
Best way to add all base properties to derived item is use reflection in costructor. Try this code, without creating methods or instances.
public Derived(Base item) :base()
{
Type type = item.GetType();
System.Reflection.PropertyInfo[] properties = type.GetProperties();
foreach (var property in properties)
{
try
{
property.SetValue(this, property.GetValue(item, null), null);
}
catch (Exception) { }
}
}
I disagree that it is not possible. You can do it like this:
public class Auto
{
public string Make {get; set;}
public string Model {get; set;}
}
public class Sedan : Auto
{
public int NumberOfDoors {get; set;}
}
public static T ConvertAuto<T>(Sedan sedan) where T : class
{
object auto = sedan;
return (T)loc;
}
Usage:
var sedan = new Sedan();
sedan.NumberOfDoors = 4;
var auto = ConvertAuto<Auto>(sedan);
This is how I solved this for fields. You can do the same iteration through properties if you want. You may want to do some checks for null etc. but this is the idea.
public static DerivedClass ConvertFromBaseToDerived<BaseClass, DerivedClass>(BaseClass baseClass)
where BaseClass : class, new()
where DerivedClass : class, BaseClass, new()
{
DerivedClass derived = (DerivedClass)Activator.CreateInstance(typeof(DerivedClass));
derived.GetType().GetFields().ToList().ForEach(field =>
{
var base_ = baseClass.GetType().GetField(field.Name).GetValue(baseClass);
field.SetValue(derived, base_);
});
return derived;
}
You can just serialize the base object to JSON and then deserialize it to the derived object.
No, see this question which I asked - Upcasting in .NET using generics
The best way is to make a default constructor on the class, construct and then call an Initialise method

Is there anyway to reconstruct an object inside itself?

I have a simple class that is intended for options of an winforms application. There should be a method that reset options to their default values. I know I can add a separate method to take care of this, but the code will be huge (If I add more options to the class) :
public SensorOptions()
{
ShowLabelMax = ShowLabelMin = ShowLabelAvr = ShowReceivedTextBox = true;
ChartMaxValue = 140;
ChartMinValue = -40;
ShowChartMinValue = ShowChartMaxValue = ShowChartAvrValue = ShowChartAvrLine = true;
LogFolder = Environment.SpecialFolder.MyDocuments.ToString();
LoggingEnabled = true;
}
public void ResetOptions()
{
this = new SensorOptions(); //can not do. 'this' is read-only
}
I mean I can copy/paste the code from constructor into ResetOptions() method. But is there any smarter ways to achieve this?
You cannot assign this because you may have references to this instance of your class in your program. If you could re-construct the object by re-assigning this, it would mean that all references to the old instance of the class become invalid.
No matter how many options you have in your class, you initialize each of them one or the other way (because you mention default value in your question - so you need to assign that default value somewhere at least once, probably in the constructor). Therefore, the solution to your problem is simple - move all initializers to the separate method and call it in the constructor, and then also call it every time you need to reset your options to their default values.
If any of your options are not assigned a default value explicitly, and use system default and you don't want to write option=default(optionType) for each option, you can use reflection to enumerate all fields/properties in that class and assign default values to them, like this:
public static object GetDefault(Type type)
{
if(type.IsValueType) return Activator.CreateInstance(type);
return null;
}
foreach(var field in this.GetType().GetFields())
field.SetValue(this, GetDefault(field.FieldType));
foreach(var prop in this.GetType().GetProperties())
prop.SetValue(this, GetDefault(prop.PropertyType));
Move all of the code from the constructor into the ResetOptions method, then in your constructor call the ResetOptions method. Your initialisiation code is only in one place then.
You have very simple architecture for your situation. In my opinion it would be better to apply a trick for this:
you have class for holding all your options (pseudo code):
class AllOptionsBackstage
{
public bool ShowLabelMax { get; set; }
public bool ShowLabelMin { get; set; }
public bool ShowLabelAvr { get; set; }
public AllOptionsBackstage()
{
// apply default values here
}
}
.....
class MyOptions
{
private AllOptionsBackstage _options;
public MyOptions()
{
Reset();
}
public bool ShowLabelMax
{
get{ return _options.ShowLabelMax; }
set{ _options.ShowLabelMax = value; }
}
public bool ShowLabelMin
{
get{return _options.ShowLabelMin;}
set{_options.ShowLabelMin=value; }
}
public bool ShowLabelAvr
{
get{ return _options.ShowLabelAvr;}
set{ _options.ShowLabelAvr = value; }
}
public void Reset()
{
_options = new AllOptionsBackstage(); // will reset all your options to default
}
}

Creating a non-static version of compiler-based "dictionary" where keys are types

There is a very easy trick which creates a dictionary-like structure where keys are types.
The structure acts like a Dictionary<Type, T?> where keys are Type objects and values are instances of the corresponding types.
This wonderful structure is as fast as just a variable or array since the "lookup" is only done once by the compiler/JITter and the proper value reference is compiled into your program.
public static class MyDict<T> {
public static T Value { get; set; }
}
You can work with that structure like this:
MyDict<string>.Value = MyDict<int>.Value.ToString();
The problem is that this "dictionary" is global. The only way to create different dictionaries is to create different classes.
How can create a similar (fastest "lookup", no boxing) non-static structure? (Without code generation.)
Simply said: I want to have multiple Dictionary<Type, object>-like objects without lookup costs, casting and boxing.
Here's an approach that extends the method described in the question:
public class TypeDict
{
public T Get<T>()
{
return MyDict<T>.Values[this];
}
public void Set<T>(T value)
{
MyDict<T>.Values[this] = value;
}
private static class MyDict<T>
{
public static Dictionary<TypeDict, T> Values { get; private set; }
static MyDict()
{
Values = new Dictionary<TypeDict, T>();
}
}
}
Now we can use the TypeDict like this:
void X()
{
var a = new TypeDict();
var b = new TypeDict();
a.Set<int>(1);
a.Set<double>(3.14);
a.Set("Hello, world!");
//Note that type inference allows us to omit the type argument
b.Set(10);
b.Set(31.4);
b.Set("Hello, world, times ten!");
Console.WriteLine(a.Get<int>());
Console.WriteLine(a.Get<double>());
Console.WriteLine(a.Get<string>());
Console.WriteLine();
Console.WriteLine(b.Get<int>());
Console.WriteLine(b.Get<double>());
Console.WriteLine(b.Get<string>());
}
Ark-kun is using generics to essentially generate unique types at compile time. With a generic type, any static members are unique to that specific closed generic type. This way it's processed as fast as a standard static member lookup.
The above usage is equivalent to something like this:
public static class MyDict_String
{
public static string Value { get; set; }
}
public static class MyDict_Int32
{
public static int Value { get; set; }
}
MyDict_String.Value = MyDict_Int32.Value.ToString();
AFAIK, types are "static" (in that you can't define more than one that way) so I don't know of a way to cheat around this and maintain the same performance of a statically compiled member lookup.
Your best bet otherwise (I think) is to create a generic instance type that wraps its own dictionary that uses System.Type for its keys and System.Object for its values to which you have to perform boxing/casting when inserting/retrieving values.
EDIT: Here's a simple implementation wrapping a dictionary:
public class MyTypedDict
{
private Dictionary<Type, object> Values = new Dictionary<Type, object>();
public T Get<T>()
{
object untypedValue;
if (Values.TryGetValue(typeof(T), out untypedValue))
return (T)untypedValue;
return default(T);
}
public void Set<T>(T value)
{
Values[typeof(T)] = value;
}
}
Thinking about it more, it might be possible to achieve a more property-like syntax using an ExpandoObject (http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx) through some tomfoolery, but I feel like this would be pretty abusive and I can only assume terribly prone to runtime errors. (plus it would afford you nothing at compile time)
EDITx2: If you really want to have different sets of values, you could nest it within another generic type:
public static class ValueSets<T>
{
public static class MyDict<U>
{
public static U Value { get; set; }
}
}
With usage like:
ValueSets<int>.MyDict<string>.Value = "Hello ";
ValueSets<bool>.MyDict<string>.Value = "World!";
string helloworld = ValueSets<int>.MyDict<string>.Value + ValueSets<bool>.MyDict<string>.Value;
Console.WriteLine(helloworld);//Hello World!
But then the initial type int and bool in this case become "magical" and without meaning, plus you would need to provide a unique type per distinct set of values you'd like to use. Plus you could not pass it around and modify as an instance variable, rather it'd be statically accessible (so long as you have access to use the type T). So perhaps you could declare minimally visible types that are named with meaning and use those:
internal class MyFirstWords {}
internal class MySecondWords {}
ValueSets<MyFirstWords>.MyDict<string>.Value = "Hello ";
ValueSets<MySecondWords>.MyDict<string>.Value = "World!";
string helloworld = ValueSets<MyFirstWords>.MyDict<string>.Value + ValueSets<MySecondWords>.MyDict<string>.Value;
Console.WriteLine(helloworld);//Hello World!
Regardless, I think this is quite wacky and I wouldn't recommend it.
A more complicated version. Don't know if it's closer:
Define a generic dictionary:
public class MyDictionary<T>
{
Dictionary<string, T> dict;
public MyDictionary()
{
dict = new Dictionary<string, T>();
}
public T this[string name]
{
get
{
if (dict.ContainsKey(name))
return dict[name];
else
return default(T);//or throw
}
set
{
dict[name] = value;
}
}
}
Then a repository to store those dictionaries:
public class MyRepository
{
List<object> repo;
public MyRepository()
{
repo = new List<object>();
}
public void Add<T>(string name, T value)
{
if (!repo.OfType<MyDictionary<T>>().Any())
repo.Add(new MyDictionary<T>());
var dict = repo.OfType<MyDictionary<T>>().FirstOrDefault();
dict[name] = value;
}
public T GetValue<T>(string name)
{
if (!repo.OfType<MyDictionary<T>>().Any())
return default(T);//or throw
else
{
var dict = repo.OfType<MyDictionary<T>>().FirstOrDefault();
return dict[name];
}
}
}
And finally you may use this repository:
MyRepository repo = new MyRepository();
repo.Add("A", 1);
repo.Add("B", 1);
int i = repo.GetValue<int>("A") + repo.GetValue<int>("B");
In this example, there is MyDictionary<T> boxing to object is left.
From the other side, if your are working with some certain types you may not use thie repository class at all. But utilize separate dictionaties.
MyDictionary<int> intDict = new MyDictionary<int>();
intDict["A"] = 1;
intDict["B"] = 2;
int i = intDict["A"] + intDict["B"];
However it's the same as working with
Dictionary<string, int> intDict = new Dictionary<string, int>();
So the MyRepository class may be edited to use Dictionary<string, T> instead of MyDictionary<T>.
#Konstantin's answer made me remember that there is actually a very fast lookup method - array indexing. This crude PoC code shows a variant of the required structure.
public class TypeDictionary {
static int _maxId = 0;
int _id;
static class Store<T>{
internal static List<T> Values = new List<T>();
}
public TypeDictionary() {
_id = _maxId++;
}
public T GetValue<T>() {
return Store<T>.Values[_id];
}
public void SetValue<T>(T value) {
while(Store<T>.Values.Count < _id) {
Store<T>.Values.Add(default(T));
}
Store<T>.Values[_id] = value;
}
}
This code can be used as follows:
var dict1 = new TypeDictionary();
dict1.SetValue("my string");
string result = dict1.GetValue<string>();
The problem with this solution is it's memory usage caused by the repository being not sparse. This also makes first time value setting more expensive.
Try this:
public class MyDictionary
{
List<object> values;
public MyDictionary()
{
values = new List<object>();
}
public T GetValue<T>()
{
return values.OfType<T>().FirstOrDefault();
}
public bool Add<T>(T value)
{
if (values.OfType<T>().Any())
return false;
else
{
values.Add(value);
return true;
}
}
}
and use it:
var md = new MyDictionary();
md.Add("!!!");
string s = md.GetValue<string>();
This class may store up to one value of type T. But there could corner cases with derived classes and interfaces I guess. You may check, if it suits your need, and probably modify it as you need, if it's close to what you need in general.
What you are looking for is impossible in C#. The language does not support a container that could store multiple objects of different types yet provides a look up method that does not involve casting, boxing or unboxing. You could accomplish something like this with macros in C++, or via a language like javascript where the structure of types can be changed at run-time.
The usage case you are describing fits quite closely with the purpose for which ConditionalWeakTable<TKey,TValue> was added to .NET 4.0. For the purpose you describe, you would include such a table in a static generic class, and then for every class object that's supposed to contain a reference to an item of a particular type you would store into that type's table a reference to object that's supposed to contain the item along with either a reference to the item, or else a reference to a simple item-holder object (note that entries in ConditionalWeakTable will evaporate when an object ceases to exist, but are otherwise immutable, so if you want a mutable association you'll need to create an object to hold it).
Building on #phoog's example with #supercat's suggestion
public class TypeDict
{
public T Get<T>() where T : class
{
T value;
InnerDict<T>.Values.TryGetValue(this, out value);
return value;
}
public void Set<T>(T value) where T : class
{
var cwt = InnerDict<T>.Values;
// lock+remove+add https://github.com/dotnet/coreclr/issues/4545
lock (cwt)
{
cwt.Remove(this);
cwt.Add(this, value);
}
}
private static class InnerDict<T> where T : class
{
public static ConditionalWeakTable<TypeDict, T> Values { get; private set; }
static InnerDict()
{
Values = new ConditionalWeakTable<TypeDict, T>();
}
}
}

How can I create temporary objects to pass around without explicitly creating a class?

I frequently find myself having a need to create a class as a container for some data. It only gets used briefly yet I still have to create the class. Like this:
public class TempObject
{
public string LoggedInUsername { get; set; }
public CustomObject SomeCustomObject { get; set; }
public DateTime LastLoggedIn { get; set; }
}
public void DoSomething()
{
TempObject temp = new TempObject
{
LoggedInUsername = "test",
SomeCustomObject = //blah blah blah,
LastLoggedIn = DateTime.Now
};
DoSomethingElse(temp);
}
public void DoSomethingElse(TempObject temp)
{
// etc...
}
Usually my temporary objects have a lot more properties, which is the reason I want to group them in the first place. I wish there was an easier way, such as with an anonymous type. The problem is, I don't know what to accept when I pass it to another method. The type is anonymous, so how am I supposed to accept it on the other side?
public void DoSomething()
{
var temp = new
{
LoggedInUsername = "test",
SomeCustomObject = //blah blah,
LastLoggedIn = DateTime.Now
};
// I have intellisense on the temp object as long as I'm in the scope of this method.
DoSomethingElse(temp);
}
public void DoSomethingElse(????)
{
// Can't get my anonymous type here. And even if I could I doubt I would have intellisense.
}
Is there a better way to create a temporary container for a bunch of different types, or do I need to define classes every time I need a temporary object to group things together?
Thanks in advance.
Tuple may be the solution you're looking for.
public void DoSomething()
{
var temp = Tuple.Create("test", "blah blah blah", DateTime.Now);
DoSomethingElse(temp);
}
public void DoSomethingElse(Tuple<string, string, DateTime> data)
{
// ...
}
The rules state that
You cannot declare a field, a property, an event, or the return type
of a method as having an anonymous type. Similarly, you cannot declare
a formal parameter of a method, property, constructor, or indexer as
having an anonymous type.
Personally, I would just bite the bullet on this one to preserve compile time integrity.
The Tuple is the clean way to go, but just to let you know that C# doesn't let you down even otherwise and to answer the question, this is how DoSomethingElse could look like:
private static void DoSomething(object temp)
{
var typedTemp = CastToType(temp, new
{
LoggedInUsername = "dummy",
SomeCustomObject = "dummy",
LastLoggedIn = DateTime.Now
});
Console.WriteLine(typedTemp.LastLoggedIn);
}
private static T CastToType<T>(object obj, T type)
{
return (T) obj;
}
PS: Don't -1, I won't use this, I don't ask you to use this :)
You can pass around anonymous types by declaring the parameter dynamic under C# 4. That said, I would not recommend this except in private methods. You lose type-safety, IntelliSense, and readability.
You could also use non-generic container classes such as ArrayList. But then you're back to casting, which is why we got generics in the first place.
Personally I'd create the class. Look to see if there's an abstraction that covers all your types and declare that as an interface, then use a generic container of that type.
public class GenericObjs
{
private List<object> objs = new List<object>();
public List<object> Objs { get { return objs; } set { objs = value; } }
public GenericObjs(List<object> Objs) { objs = Objs; }
}
You could include List String and a constructor for List String ...
I just don't come across the need for throw away classes. If the business object has structure then a class is the way to define and enforce that structure and it is not much code.

How to implement a class to access objects of several different types in C#?

I'm trying to implement a class to access items of different types, in a similar way to database rows.
However, I have two different ideas in mind, and I don't know which one to choose:
Design 1
public enum ObjectTypeA
{
Undefined,
Integer,
Float
}
public class MyObjectA
{
private object val;
public ObjectTypeA Type
{
get;
private set;
}
public int Integer
{
get
{
if (Type != ObjectTypeA.Integer) throw new Exception();
return (int)val;
}
set
{
Type = ObjectTypeA.Integer;
val = value;
}
}
public float Float
{
get
{
if (Type != ObjectTypeA.Float) throw new Exception();
return (float)val;
}
set
{
Type = ObjectTypeA.Float;
val = value;
}
}
}
Less compile-time checks possible.
Can't use the is operator, GetType(), etc. (reinvents the type system).
Boxing and unboxing for value types.
Can be inherited by other classes (e.g. I can create a "named object" using inheritance).
Design 2
public abstract class MyObjectB
{
}
public class MyIntegerB : MyObjectB
{
public int Value
{
get;
set;
}
public MyIntegerB(int _value)
{
Value = _value;
}
}
public class MyFloatB : MyObjectB
{
public float Value
{
get;
set;
}
public MyFloatB(float _value)
{
Value = _value;
}
}
Shorter and simpler implementation.
Very verbose (casting) to use.
Performance is not critical, but it's still important, since most of the objects that are going to be stored are integers or floats, so boxing overhead matters.
The classes will just contain the values, not methods that depend on the type, etc. so it doesn't matter if the solution uses inheritance.
IMPORTANT: One of the requirements is that there may be two types that use the same underlying type (e.g. two classes derived from MyObjectB may use int as the Value), so using object or generics may not be possible.
Any suggestion about which design to use, or another different design?
EDIT:
The reason I don't like the second one is because it's very verbose to use:
MyObjectB objB = new MyIntegerB(12);
Console.WriteLine(((MyIntegerB)objB).Value);
And because I can't inherit it to create something like a "named object", so I have to attach MyObjectB to the class, and the usage is even more verbose.
I don't see why you wouldn't use generics here. More strongly: I don't see why you need this at all: It seems like Nullable<T> would cover all of your use cases very nicely. If not, implementing this generically is trivial:
public class ValueWrapper<T>
{
public T Value
{
get;
private set;
}
public Type WrappedType
{
get { return typeof(T); }
}
}
public MySpecialInt : ValueWrapper<int>
{
/* etc */
}
why not use generics?
public abstract class MyObjectB<T>
{
public T Value
{
get;
set;
}
public MyObjectB(T _value)
{
Value = _value;
}
}
you only need one class at this point. just instantiate it differently:
var myObj = new MyObjectB<Int>(1);
or
var myObj = new MyObjectB<Float>(0.012);
I know you mentioned not wanting to deal with boxing and unboxing, but I still think a Generic class would be your best bet here.
public class MyObject<T>
{
public MyObject(T t) {
Value = t;
}
public T Value { get; set; }
}
Edit:
One of the requirements is that there
may be two types that use the same
underlying type (e.g. two classes
derived from MyObjectB may use int as
the Value), so using object or
generics may not be possible.
That would only apply if you're extending the class. There's no problem if you wrap the class instead, i.e. create a MyObject<int> and access its Value property, rather than subclassing it.
Having said that, if you want to subclass a generic class, the subclass would also need to be a generic class.
Have you considered generics?
public class MyObjectA<T> {
public T Value {
get; set;
}
}
I've written a similar class that could hold either a single instance of ClassX or an array of ClassX. The trick was that it could change during runtime, so a generic wouldn't suffice, but I still wanted it strong-typed in all cases. It sounds like that's similar to what you're trying to accomplish here.
I chose the first option, and here's why: Wherever possible, I encapsulate complexity within a class to make the class easier to use. Classes should encapsulate away complexity from the caller, making calls to it more concise. If using MyObjectB makes your code more verbose, than I don't think that's the right answer.
if you need heterogeneous collections then this would do.
public enum ObjectTypeA
{
Undefined,
Integer,
Float
}
public class MyObjectA
{
public MyObjectA(object value) : this(value, InfereType(value))
{ }
public MyObjectA(object value, ObjectTypeA type)
{
Value = value;
Type = type;
}
public object Value { get; private set; }
public ObjectTypeA Type
{
get;
private set;
}
public T ValueAs<T>()
{
return (T)Value;
}
}
then use it like
List<MyObjectA> list = GetAllValues();
foreach (var item in list)
{
switch (item.WrappedType)
{
case MyObjecttypeA.Float:
float f = item.ValueAs<float>();
// do something with float
}
}

Categories