I am new to C#. I am trying to implement a Dictionary in C# whose Java-equivalent is:
HashMap<string, Variable<?>> dictionary
Here is the detailed Java version of what I'm trying to do: Java how to manage user-defined variables
In C# so far I have something like this:
interface IVariable { }
public class Variable<T> : IVariable
{
public T myValue { get; set; }
}
Dictionary<string, IVariable> vars = new Dictionary<string, IVariable>();
Then I try to do this:
Variable<int> age = new Variable<int>();
age.myValue = 12;
vars.Add("age", age);
IVariable theVar;
if (vars.TryGetValue("age", out theVar) {
Console.WriteLine("fetched age is " + theVar.myValue);
}
I run into trouble in the last line because the compiler doesn't recognize the myValue member of a theVar because it is an IVariable.
In this simple example maybe I could declare theVar to be a Variable<int> instead of an IVariable but I haven't tried it because it would require a priori knowledge about what kind of variable I'm fetching from the dictionary and I might not always have that knowledge.
I wouldn't mind if myValue were an inherited/abstract property (if there is such a thing), since every Variable will have a property named myValue (each will differ in type but not in name). In that case I guess I could make IVariable an abstract class rather than an interface, but then I still run into trouble as far as what to put for the type of myValue.
Could I do a cast of theVar into something using as by first checking its type with is? I'm not sure if that would work or is even possible.
I've looked at these posts for guidance (especially the second one):
Wildcard equivalent in C# generics
C# Generics: wildcards
However, my situation is still slightly different than the second example above because that example has an abstract method that is returning a void whereas I wish to have my variables return non-void generic values.
Thanks for any help.
C# has dynamic. You can create Dictionary<string, dynamic>
Or you can use object (boxing/unboxing) Dictionary<string, object>
Or you can get generic type from class
class MyClass<TDicValue>
{
Dictionary<strint, TDicValue> myDictionary;
}
I had this same problem where I had 20 slightly different types and I had to keep dictionaries on. I wanted to organize them in a list.
The problem was the same, selecting the right kind from the list with reflection or strings lacked the ability to provide a type to return to. #skrilmps answer is correct, but packing and and unpacking was at best unreliable without a lot (metric ton) of ugly messy code.
While unity does support dynamics in 2020, this doesn't exactly work with what i am doing unless I make like everything dynamic safe and that's shamble coding, not extensible or maintainable, and just sounds like a general nightmare.
I personally feel that I am an inadequate programmer after years of trying to learn and still not having my efforts provide a productive return or product of note, so i cannot claim the answer being mine, but in my research on the proper solution to this problem i found this: https://www.youtube.com/watch?v=A7qwuFnyIpM
In here he says basically if you add an interface to your similar classes that are intended for use in a variety of different lists, that you can instead make a list of that type of interface. I would assume dictionary as well, and then you can add any kind of class implementing this interface to this singular interface type defined list.
I tried using boxing/unboxing and came up with this solution. It appears to work... so far. But it doesn't seem very safe.
public interface Variable
{
object getValue();
void setValue(object value);
Type myType();
}
public class Variable<T>: Variable
{
private T myValue;
public object getValue()
{
return myValue;
}
public void setValue(object value)
{
myValue = (T)value;
}
public Type myType() { return myValue.GetType(); }
}
Dictionary<string, Variable> vars = new Dictionary<string, Variable>();
Variable<int> age = new Variable<int>();
age.setValue(21);
vars.Add("age", age);
Variable theAgeVar;
vars.TryGetValue("age", out theAgeVar);
Console.WriteLine("age = " + theAgeVar.getValue());
Variable<double> height = new Variable<double>();
height.setValue(5.9);
Variable theHeightVar;
vars.TryGetValue("age", out theHeightVar);
Debug.Log("height = " + theHeightVar.getValue());
This prints:
age = 21
height = 5.9
One thing I do not like is that I had to make the return type of getValue() be an object. If I wanted myValue (which is of type T) to implement IComparable, for instance, then this information is lost when the boxing happens and the caller receives an object.
// The following should resolve the boxing problem and now is totally generic:
public interface IVariable<T>
{
T GetContent();
void SetContent(T value);
Type GetDataType();
}
public class Variable<T> : IVariable
{
private T content;
public T GetContent()
{
return content;
}
public void SetContent(T value)
{
content = value;
}
public Type GetDataType() { return GetType(); }
}
Dictionary<string, Variable<T>> variables = new Dictionary<string, Variable<T>>();
Related
Say I have the following code:
class MyField : DynamicObject
{
public dynamic Value { get; private set; }
public override bool TryConvert(ConvertBinder binder, out object result)
{
result = binder.Type == Value.GetType() ? Value : null;
return result != null;
}
public MyField(dynamic v)
{
Value = v;
}
}
// ...
public static class Program
{
static void doSomething(ulong address) { /* ... */ }
public void Main(string[] args)
{
dynamic field = new MyField((ulong)12345);
doSomething(field); // fails as field is not a ulong.
doSomething((ulong)field); // succeeds as field can be casted to a ulong.
ulong field2 = field; // also succeeds
}
}
Is there a way to get the first call to doSomething to succeed? I'm writing a library to read a particular file format which uses serialized C-style structures; reading the file entails reading these saved structure definitions and then "populating" them with the data contained in the rest of the file. I have a "structure" DynamicObject class (to support dot-notation access) and a "field" DynamicObject class, which is primarily necessary to hold additional information on the contents of the field; although I could probably get rid of it, it would make certain other operations more difficult. What I'd like to do is just "pretend" MyField is a certain type (well, technically just any built-in primitive or array of primitives, including 2D arrays) and implicitly convert it to that type. However, the runtime fails to try to implicitly convert field to the type required by the underlying method signature if field doesn't match the type required.
In the vein of Greg's answer, I came up with a solution that makes the runtime happy. It's not exactly what I was originally looking for, but it seems like the best solution.
Since I already have a large if-else tree in my source wherein I take an array of bytes and interpret them as an actual value-type, and indeed my current source does use an underlying generic MyField<T>, so this works fine. I can't recall why I wanted MyField to be dynamic in the first place.
Anyway, this is a modified solution.
class MyField<T>
{
public dynamic Value { get; private set; }
public MyField(dynamic v) { Value = v; }
public static implicit operator T(MyField field)
{
return (T)field.Value;
}
}
I keep coming back to wanting the runtime to just figure out what it needs to cast MyField to at runtime but I guess it's not that big of a deal. If anyone comes up with something better, let me know. I'm going to keep this question open in the meantime.
You potentially might want to look into Generics. Coupled with an interface may make the dynamic usage far more viable.
public interface Helper <TInput, TOutput>
{
<TOutput> DoSomething(TInput input);
}
So when you use this interface with a class, you'll implement your type for both input and output. Which will give you quite a bit of flexibility, which should avoid those cast that you mentioned earlier. A small example, I mean you could obviously adjust it based on needs but I still don't understand what you're trying to really do.
I have a bit of a strange issue here. I have a project constraint where a value of a Property needs to either be a number (int, double, long, etc are all acceptable), a string, or a datetime. The reason that the Value parameter needs to be of one these three (err..well if you count all of the possible numeric value Types allowed it's a bit more) Types is because depending on the type the underlying value will need to be converted to special formats for serialization to a REST API. To simplify things here is a basic idea of the class as a POCO:
class Foo
{
public string Name {get;set;}
public Guid Id {get; set;}
public UNKNOWN Value {get;set;}
}
I thought about using generics for this, with a where T : struct constraint, but this still leaves too many types that can theoretically be set that are actually invalid Types. Sure I can perform type checking and throw exceptions during construction/setting of the Value parameter, but this doesn't feel like "clean" code.
I took a look at this question How do you work with a variable that can be of multiple types? , but it didn't really help since it was more of an issue dealing with inheritance. However, using multiple nullable private fields and returning a single Property based on which one was populated is a possibility, but again I feel there has to be a better way.
The other possibility I was thinking of was to use the dynamic type and and perform some reflection magic to check the underlying type (and perform conversions & formatting/throw exceptions). I'm a bit scared that this will really hurt performance though.
Are there any best practices for this situation? If not, are there any better ways to handle this from what I've mentioned?
EDIT Eric Lippert taught me this type of dispatch in one of his epic stackoverflow answers, and I'm searching for it at the moment. I will update this answer with a link if/when I track it down (the man has answered quite a few questions). Also, OP, you asked about performance, take a gander at this info also from Lippert: How does having a dynamic variable affect performance?
I would use a mix of dynamic with special case handling, and a generic type catch all for undefined (not yet implemented) types.
class Foo
{
public dynamic Value { get; set; }
}
class FooHandler
{
public void Serialize(Foo foo)
{
SerializeField(foo.Value);
}
void SerializeField(int field)
{
Console.WriteLine("handle int");
}
void SerializeField<T>(T field)
{
throw new NotImplementedException("Serialization not implemented for type: " + typeof(T));
}
}
class Program
{
[STAThread]
static void Main(string[] args)
{
Foo f = new Foo();
f.Value = 1;
FooHandler handler = new FooHandler();
handler.Serialize(f);
Console.ReadKey();
}
}
And then add types at your leisure.
You could use a dedicated class as a "multiple type variable".
At instantiation time you can pass an int, double, long, etc. and when you need to get the stored value out you can use a separate call.
public class Foo
{
public class Value
{
object _value;
public Value(int value) { _value = value; }
public Value(double value) { _value = value; }
public Value(long value) { _value = value; }
// etc
public object GetValue() { return _value; }
}
public void TestCall()
{
Value myValue = new Value(123);
Debug.WriteLine(myValue.GetValue());
}
}
An object can provide its binding semantics by implementing
IDynamicMetaObject Provider—or more easily by subclassing
DynamicObject, which provides a default implementation of this
interface.
source
I never implemented this interface nor class and always been able to execute things dynamically:
public class aa
{
public void bbb()
{ }
}
dynamic a = new aa().bbb();
so what do they mean by this quote ?
im trying to understand when should i need to use IDynamicMetaObject or the DynamicObject inheritance
The dynamic keyword causes references to an object to be late-bound and only resolved at runtime. Usually, the reason for this is because you are using an IDynamicMetaObjectProvider implementer, which allows your code to decide how to treat the run-time property resolution. That is, you may want to add and remove properties at runtime (typically implemented as a dictionary, like ExpandoObject).
What your example code is doing is just preventing compile-type type checking. In fact it's worse than doing nothing, because if you wrote code that accessed a nonexistent property or method of your class, it would still compile, but of course crash at runtime. I can't think of many good reasons to refer to concrete classes with dynamic (expect for squishy typecasting or duck-typing, but we usually use interfaces for stuff like this in C#!)
Example implementation of a dynamic object that inherits DynamicObject from one of my own projects:
https://github.com/jamietre/IQObjectMapper/blob/master/source/IQObjectMapper/IQDynamicObject.cs
(It makes one call to a factory method that returns a new dictionary with options, all you need to do to make this non-dependent is change the constructor from:
InnerDict = ObjectMapper.MapperCache.GetDictionary<object>(Options);
to:
InnerDict = new Dictionary<string,object>();
and get rid of a couple conditons that check options
I hate to give "pithy" answers like this, because its not very imformative, but this really is a case of "if you needed it, you would know."
It is very rare that you would need to implement a dynamic object in an application, or even most library code. The interface is meant for people implementing classes that can only be used as dynamic objects; for example, if you wanted to implement Javascript-like behavior on your object. You can call any property or method you want on such an object, and it will compile. It's up to your implementation at run-time to figure out whether a given call works or not.
A totally pointless but descriptive example would be a class that decides which properties are valid based on the day of the week:
public class WeekendObject : DynamicObject
{
Dictionary<string, object> propertybag = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
if (name.StartsWith("Sunday"))
{
return propertybag.TryGetValue(name, out result);
}
}
else
{
if (!name.StartsWith("Sunday"))
{
return propertybag.TryGetValue(name, out result);
}
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
if (name.StartsWith("Sunday"))
{
propertybag[binder.Name.ToLower()] = value;
return true;
}
}
else
{
if (!name.StartsWith("Sunday"))
{
propertybag[binder.Name.ToLower()] = value;
return true;
}
}
return false;
}
}
I've something along this lines:
public class Something
{
private IDictionary<object,Activity> fCases;
public IDictionary<object,Activity> Cases
{
get { return fCases; }
set { fCases = value; }
}
}
public sealed class Something<T> : Something
{
private IDictionary<T,Activity> fCases;
public override IDictionary<T,Activity> Cases
{
get { return fCases; }
set { fCases = value; }
}
}
Note: override is not accepted on this case
Due to heavy Reflection usage there are situations where I've to downcast from Something<T> to Something but, I guess because Cases property is hidden, I'm losing Cases data.
How can I circumvent this situation? I've tried to use where T:object but that isn't accepted also.
EDIT:
This is an example of why I need inheritance:
if (someVar is Something) {
if (someVar.GetType().IsGenericType)
{
// Construct AnotherObject<T> depending on the Something<T>'s generic argument
Type typeArg = someVar.GetType().GetGenericArguments()[0],
genericDefinition = typeof(AnotherObject<>),
typeToConstruct = genericDefinition.makeGenericType(typeArgs);
object newAnotherObject = Activator.CreateInstance(typeToConstruct);
// Pass Something 'Cases' property to AnotherObject<T>
constructedType.InvokeMember(
"Cases",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
null,
newActivity,
new Object[] { someVar.Cases });
}
}
But, because 'Cases' is hidden, it will be always null. Without inheritance I would have to write a BIG if-then-else with all the possible generic arguments. And, believe me, I do really have to use someVar is Something and Reflection to construct all this objects. This is a big generic API being converted to other big generic API and so they should not known each other and the conversion should be as transparent as possible.
You won't be able to override it like that, and for good reason.
Imagine:
Something x = new Something<string>();
Button key = new Button();
x.Cases[key] = new Activity();
If your override worked, that would be trying to store a Button reference as a key in Dictionary<string, Activity>. That would be a Bad Thing.
Perhaps inheritance isn't actually appropriate in this case? If you could explain more about what you're trying to achieve, that would help. Perhaps you don't really need the dictionary as a property? Maybe just a method to fetch by key?
This is flat-out not going to work because the IDictionary<TKey, TValue> interface is invariant. An IDictionary<object, Activity> cannot be treated as an IDictionary<T, Activity>.
What you could do, rather than exposing an entire IDictionary<T, Activity> in your derived class, is simply delegate the calls you want to expose, like this:
public class Something
{
protected IDictionary<object, Activity> Cases { get; set; }
}
public sealed class Something<T> : Something
{
public Activity GetCase(T key)
{
return Cases[key];
}
public void AddCase(T key, Activity case)
{
Cases.Add(key, case);
}
// etc. etc.
}
Alternatively, you could also define your own contravariant interface, something like:
interface IKeyedCollection<in TKey, TValue>
{
TValue this[TKey key] { get; set; }
void Add(TKey key, TValue value);
}
For the above interface, an IKeyedCollection<object, Activity> could act as an IKeyedCollection<T, Activity> because every T is an object.
If you attempt to expose incompatible types at the different levels you're going to keep running into problems because at the end of the day you'll end up having to maintain 2 separate objects (or 1 custom object with 2 interfaces it can't completely satisfy).
These types are incompatible because there are values which can be added to IDictionary<object, Activity> which cannot be added to every instantiation of IDictionary<T, Activity>. Imagine for instance T is instatiated as string and the developer uses a int key elsewhere via Something. This creates a real problem for Something<string> implementations.
The way I would approach this is to change the base type Something to not expose a concrete type but instead to expose the relevant APIs.
public abstract class Something {
public abstract IEnumerable<KeyValuePair> GetElements();
public abstract bool TryGetValue(object key, out Activity value);
}
This gives Something<T> the flexbility it needs to properly sub-class Something and be very expressive about the types it wants to expose
public sealed class Something<T> : Something {
private IDictionary<T,Activity> fCases;
public override IDictionary<T,Activity> Cases
{
get { return fCases; }
set { fCases = value; }
}
public override IEnumerable<KeyValuPair<object, Activity>> GetElements() {
foreach (var cur in fCases) {
yield return new KeyValuePair<object, Activity>(cur.Key, cur.Value);
}
}
public override bool TryGetValue(object key, out Activity activity) {
try {
T typedKey = (T)key;
return fCases.TryGetValue(typedKey, out activity);
} catch (InvalidCastException) {
activity = null;
return false;
}
}
}
}
During heavy reflection usage I also had the need to 'upcast' from generic types. I knew certain calls would be compatible, but I didn't know the types at compile time. If you look at it this way, it is not really 'upcasting' a generic type, but rather, allowing to use generics during reflection by generating the correct downcasts.
To this end I created a helper method to create delegates along the lines of Delegate.CreateDelegate, but allowing to create a less generic delegate. Downcasts are generated where necessary. I explain it in detail on my blog.
MethodInfo methodToCall = typeof( string ).GetMethod( "Compare" );
Func<object, object, int> unknownArgument
= DelegateHelper.CreateDowncastingDelegate<Func<object, object, int>>(
null, methodToCall );
unknownArgument( "test", "test" ); // Will return 0.
unknownArgument( "test", 1 ); // Will compile, but throw InvalidCastException.
A bit later I had a need to create entire less generic wrapper classes for generic classes, so that all method calls would immediately become available as less generic calls during reflection. This might or might not be useful in your scenario as well. For this purpose I created a (not as thoroughly tested) method which allows to generate this wrapper class at runtime using emit. It is available in my open source library. I haven't written about this yet, so when interested you'll just have to try it out (and possibly see it fail since it's still quite new).
I'm creating a Settings object in my app, used for storing user-defined settings and whatnot. I plan on using various datatypes for my setting fields (ints, strings, enums, anything Serializable, really).
I'd also like, if possible, a type-safe way to set any of the settings. My proposed method would be doing something like this:
Tuple<string, Type> SettingName = new Tuple<string, Type>("NumberOfFoos",
typeof(**TYPE**));
public void Set(Tuple<string, Type> key, **TYPE** value) { /* Stuff */ }
The Tuple would effectively be the "setting" that the user would push a value to, and would consist of the key for that setting as well as the type of that setting. What I'm wondering is if there's any way to have the compiler enforce that, in the Set() method, the type of value is of the same type as the type object saved in the tuple passed to Set()? Is the way I proposed even possible? Thanks!
EDIT: I thought of some more things I should clarify.
1) This is intended to be a static class, so I won't be able to serialize the whole class, only members in it. Therefore, I'd really like to not have to deal with a serialization for each field. I was planning on storing all the setting values in a Dictionary<string, **TYPE**> and serializing that.
2) The Tuple definitions are meant to be constant and static. I'm really treating them as more of a typedef-type thing (I really should make my own SettingKey struct), which the user passes to Set to indicate what field they are changing. The Type parameter is meant to enforce the the value parameter is of the specified type.
Something like
public void Set<T>(Tuple<string,T> key, T value) { /* stuff */ }
might do it
It's better to get rid of the tuple, and use a generic method:
public void Set<T>(string key, T value);
That way, you can specify the type at compile-time
Set<string>("MyStringKey", "foo");
Set<int>("MyIntKey", 1);
or the compiler can infer it for you:
Set("MyStringKey", "foo");
Set("MyIntKey", 1);
and in Set, you can use typeof(T) to get the Type object you would have passed in.
Why not simply add strongly typed properties to your settings object? e.g. public int NumberOfFoos {get {} set {...}} and in the getter and setter call your common serialization and deserialization code.
If you do this your settings object isn't exposing how it works internally and you have full intellisense support on it.
Well, if you did something like Set<T>(Tuple<string, T>, T value), you'd get what you're after for setting. And I think the compiler could infer the T in Set<T>() at usage, so you would have to write it.
But your Get<T>(), you'd have to specify the type you expected to get back.
public class Foo
{
Tuple<string, Type> SettingName = new Tuple<string, Type>("NumberOfFoos",
typeof(**TYPE**));
public void Set(Tuple<string, Type> key, object value)
{
if(value.GetType() != SettingsName.Value)
throw new ArgumentException("value");
}
}
You would be better of using generics like in the other answers though.
I don't think you need to deal with Types at all. Would something like this be good enough?
class Settings {
public static int Foo {
get { return (int)_map["Foo"]; }
set { _map["Foo"] = value; }
}
public static string Bar {
get { return (string)_map["Foo"]; }
set { _map["Foo"] = value; }
}
// ...
private static Dictionary<string, object> _map =
new Dictionary<string, object>();
}
You'd then serialize the dictionary. You could even use some code-generation to create this class.