Creating a Generic Class Member for Extra Info - c#

I'm very new to C# (this is my first C# project). I'm fairly confident with the basics, but I'm starting to run into things that are raising issues that I can't quite solve, no matter how many different ways I Google it. A LOT of my questions have been answered by this site. :]
So, since I can't find the answer to this question, I decided to post it myself.
Maybe it's too basic of a question that everyone pretty much knows it, but I couldn't figure this out from the MSDN reading.
It has to do with C# Generics. I'm programming for a video game engine, and I've created a simple messaging system between AI units. The Message class contains members like sender, receiver, dispatchTime, and extraInfo. I want to use the extraInfo member to be a useful, flexible addition to the Message class, so I would like for it to be able to contain any type (an int node index, a double path cost, a relevant Vector3 position from XNA, etc, etc...). My research for this pointed me in the direction of Generics.
I figured out how to use Generics in something like a List, but I haven't read anything about how to just declare and implement a generic -member-. Just a single member, not a collection.
How would I declare this member, extraInfo? Additionally, when accessing it from another class, I would like to be able to type:
info = message.extraInfo;
..to retrieve the extra information via the get property.
How would this be done in C#?

Your message class would look something like this
public class Message<T>
{
public object Sender { get; set; }
public object Receiver { get; set; }
public T ExtraInfo { get; set; }
}
public static void Main()
{
Message<double> doubleMessage = new Message<double>() { ExtraInfo = 4.0d };
Message<string> stringMessage = new Message<string>() { ExtraInfo = "Hello World" };
}

Using .NET 4.0, you can make your ExtraInfo property of type dynamic. You could then store anything at all in it, and as long as you access it properly at runtime, you'll be ok.

You could declare the extraInfo member of your class as an object. You could then put anything you want in there.

You can solve your problem by creating an ExtraInfoType object that contains an
object as well as implicit operators to convert to and from the various object types transparently.
The ExtraInfoType object can also indicate what kind of object is stored in the ExtraInfoType.
An example of this implementation is below.
enum ExtraInfoKind
{
Integer,
Double
}
class ExtraInfoType
{
object value;
public object Value {
get { return value; }
}
ExtraInfoKind kind;
public ExtraInfoKind Kind {
get { return kind; }
}
private ExtraInfoType(object o, ExtraInfoKind kind){
this.value=o;
this.kind=kind;
}
public static implicit operator int(ExtraInfoType o){
if(o.kind!= ExtraInfoKind.Integer)
throw new InvalidCastException();
return (int)o.value;
}
public static implicit operator double(ExtraInfoType o){
if(o.kind!= ExtraInfoKind.Double)
throw new InvalidCastException();
return (double)o.value;
}
public static implicit operator ExtraInfoType(int o){
return new ExtraInfoType(o, ExtraInfoKind.Integer);
}
public static implicit operator ExtraInfoType(double o){
return new ExtraInfoType(o, ExtraInfoKind.Double);
}
}
/* Example
class Program
{
public static void Main(string[] args)
{
ExtraInfoType t=1;
Console.WriteLine(t.Kind);
int valueT=t;
Console.WriteLine(t);
Console.ReadLine();
}
}
*/
Here you would declare extraInfo under the type ExtraInfoType.
Note that no generics are necessary here. Note also that ExtraInfoType
can store only one kind of object, which can be determined by the Kind property.
If the object is cast to the wrong type, an InvalidCastException is thrown, as
can be seen in the implicit operators above.

Related

How to create a data store with a dictionary of objects holding a generic field

I'm currently trying to wrap my head around C#'s generics and I'm either missing some piece of info or I'm going about it all wrong. I have a class called WatchedVariable:
class WatchedVariable<T>
{
private T Data { get; set; }
public WatchedVariable(T initVal)
{
Data = initVal;
}
public T GetVal()
{
return Data;
}
public void SetData(T newVal)
{
Data = newVal;
}
}
The point of this class is to hold a value that can be of any type as I do not know what the type will be at runtime.
I also have a DataStore used to hold a Dictionary of these WatchedVariable objects:
class DataStore
{
private Dictionary<string, WatchedVariable<T>> _store;
public DataStore()
{
_store = new Dictionary<string, WatchedVariable>();
}
public void AddToStore(string varname, WatchedVariable variable)
{
_store.Add(varname, variable);
}
public string GetFromStore(string key)
{
return _store[key].GetVal();
}
public void ChangeValInStore(string key, string newVal)
{
_store[key].SetData(newVal);
}
}
My question is how do I go about setting up the _store Dictionary so that it can take these generic WatchedVariable objects. Currently the compiler is mad at me for placing next to the WatchedVariable for the _store Dictionary value. I want to avoid placing on the DataStore class itself since that would essentially lock me into a specific type, which I don't want to do. Again, either I'm going about this all wrong or something I'm just missing here.
I do not know what the type will be at runtime.
This is beyond the ability of Generics. Generics are specifically there to allow you to put in any type while maintaining Compile Time Type safety.
There is some leeway with co- and contravariance (which imitates casting within the same class heirarchy for the generic type), but maintaining compile time type safety was a important reason for their existence.
Otherwise we would just use the equivalent of List<Object> everwhere and call it a day.

Passing an Enum as an argument

I am playing around with trying to make a simple Roguelike game to learn C# a bit better. I am trying to make a general method that I can give it an Enum as an argument, and it will return how many elements are in that Enum as an int. I need to make it as general as possible, because I will have several different classes calling the method.
I have searched around for the last hour or so, but I couldn't find any resources here or otherwise that quite answered my question... I'm still at a beginner-intermediate stage for C#, so I am still learning all the syntax for things, but here is what I have so far:
// Type of element
public enum ELEMENT
{
FIRE, WATER, AIR, EARTH
}
// Counts how many different members exist in the enum type
public int countElements(Enum e)
{
return Enum.GetNames(e.GetType()).Length;
}
// Call above function
public void foo()
{
int num = countElements(ELEMENT);
}
It compiles with the error "Argument 1: Cannot convert from 'System.Type' to 'System.Enum'". I kind of see why it won't work but I just need some direction to set everything up correctly.
Thanks!
PS: Is it possible to change the contents of an enum at runtime? While the program is executing?
Try this:
public int countElements(Type type)
{
if (!type.IsEnum)
throw new InvalidOperationException();
return Enum.GetNames(type).Length;
}
public void foo()
{
int num = countElements(typeof(ELEMENT));
}
You could also do this with a generic method. Personally I like the syntax better for the foo() method this way, since you don't have to specify typeof()
// Counts how many different members exist in the enum type
public int countElements<T>()
{
if(!typeof(T).IsEnum)
throw new InvalidOperationException("T must be an Enum");
return Enum.GetNames(typeof(T)).Length;
}
// Call above function
public void foo()
{
int num = countElements<ELEMENT>();
}

Implementing a class from 2 interfaces that share some parts

Is the following not a good practice?
public interface IMyImmutableData
{
int Data { get;}
}
public interface IMyMutableData
{
int Data { set;get;}//implements both get and set
}
public class MyData : IMyImmutableData, IMyMutableData
{
public int Data{get;set;} //implements both IMyImmutableData, IMyMutableData
}
void Main()
{
MyData myData = new MyData{Data=10};
Console.WriteLine(myData.Data);
}
The reason I ask is that resharper gives me the following warning: "possible ambiguity while accessing by this interface"
The reason I want to do the above is that when I create methods that use the MyData class, I would like to send it either as IMyMutable or IMyImmutable objects, so that users of the method know that they can expect the method to update or not update the passed in object.
I think you can ignore resharper's warning, as the ambiguity is intentional.
However, usually a wrapper class is used to provide readonly access to something, that way it can't be cast to anything that does provide more functionality.
public class MyReadonlyData : IMyReadonlyData {
private MyData instance;
public int Data {
get {
return instance.Data;
}
}
public MyReadonlyData( MyData mydata ) {
instance = mydata;
}
}
// no access to original object or setters, period.
You need to make one or both of the implementations explicit:
public int IMyImmutableData.Data { get; }
public int IMyMutableData.Data { get; set; }
When you mark one as explicit, it can only be accessed when specifically cast as that type:
MyData obj = new MyData();
obj.Data; // Doesnt exist
(obj as IMyImmutableData).Data // Exists, specifically cast as this interface
If you choose to not mark one as explicit, it will be the property chosen when cast as other appropriate types.
I think in this case your structure is fine. You don't want to explicitly implement the interfaces via separate properties, because then the Data you access via the immutable interface will actually be different than that for the mutable interface.
Also, your actual code is likely more complex, because in this case there is no ambiguity: you are accessing Data via the object itself, so interfaces need not be considered.
One solution with explicit interface implementation would be to use a common backing field, rather than auto-properties:
private int _data;
public int IMyImmutableData.Data
{
get
{
return this._data;
}
}
public int IMyMutableData.Data
{
get
{
return this._data;
}
set
{
this._data = value;
}
}
You could cast the variable and tell the compiler what exactly you mean: (resolve ambiguity)
MyData myData = new MyData{Data=10};
Console.WriteLine( ((IMyMutableData)(myData)).Data );
You need a combined interface with a "new" qualifier on the read-write interface to avoid the squawk. Further, your interfaces are poorly named. Better names would be something like "IReadableData" and "IWritableData", and "IReadWriteData". Note that while "IReadableData" does not provide any means of mutating the data, that by no stretch of the imagination implies that the data is immutable. If something is immutable it won't every be changed by anyone; that would clearly not be the case with an object of type MyData.

Design problem causing inability to get returned proper dataType

I have an object that has properties of another object and one called DataValue, but the type that I want DataValue to return depends on information contained in the object in the other property. I'm not convinced my way is the best way to do this.
I have this business object called an AssetStructure.
An AssetStructure object contains a generic list of IAssetStructureField objects, which are a series of objects that basically hold information about the data that can be held in that field, a default value of a certain datatype and some displaying information properties. Each of the objects implementing the IAssetStructureField interface will hold different datatype. For example, one's DefaultValue's type maybe string and the other maybe a List<ofCustomType>.
I have my Asset object containing a generic list of objects called AssetDataField. The AssetDataField has properties of one containing the AssetStructureField and one called DataValue, the Asset's data for that StructureField.
My problem is datatype of AssetDataField DataValue property, it will need to be different depending on the details of the AssetStructureField object. This StructureField may hold data representing all the user groups with access to the Asset (datatype List<UserGroups>), and another might just be a description field (datatype string), so I need the DataValue coming out of the AssetDataField to be of the same type.
What I'm thinking of doing now, and that I feel can probably be done much better, is having the AssetDataField.DataValue return an object, and then cast it to the typeof the AssetDataField.StructureField.DefaultValue.
object fieldValue;
object fieldDefaultValue;
Asset certainAsset = new Asset(32423);
foreach (AssetDataField dataField in certainAsset.DataFields)
{
fieldDefaultValue = datafield.StructureField.DefaultValue;
fieldValue = datafield.DataValue as typeof(fieldDefaultValue);
// then do stuff depending on what typeof(fieldValue) is. This is where I
// see things getting particularly ugly. Not only just because that
// this class here will need to know the possible types that may be
// returned, so it can deal.
if (typeof(fieldValue) == whatever)
{
// deal;
}
else if (typeof(fieldValue) == whatever2)
{
// deal differently;
}
}
Does anyone have any suggestions? I am not a opposed, at all, to a complete redo. I'm really sorry this is so long-winded, I just wanted to try and explain the situation well. I tried to put together a UML diagram to help out, but my ArgoUML was acting up. Thanks for any insights at all that you can provide.
It seems like you should make AssetDataField a possibly abstract base class, and derive other classes from it to perform the work. For example:
class Program
{
static void Main(string[] args)
{
Asset certainAsset = new Asset(32423);
foreach (AssetDataField dataField in certainAsset.DataFields)
{
dataField.Deal();
}
}
}
class Asset
{
public List<AssetDataField> DataFields = new List<AssetDataField>();
public Asset(int id)
{
// Load asset #id
if (id == 32423)
{
DataFields.Add(new AssetDataFieldString());
DataFields.Add(new AssetDataFieldFloat());
}
}
}
abstract class AssetDataField
{
public AssetDataField()
{
FieldValue = DefaultValue;
}
public abstract object DefaultValue { get; }
public abstract object FieldValue { get; set; }
public abstract void Deal();
}
abstract class AssetDataFieldType<T> : AssetDataField
{
protected T internalValue;
public override object FieldValue
{
get
{
return TypedValue;
}
set
{
TypedValue = (T)System.Convert.ChangeType(value, typeof(T));
}
}
public virtual T TypedValue
{
get
{
return internalValue;
}
set
{
internalValue = value;
}
}
}
class AssetDataFieldString : AssetDataFieldType<string>
{
public override object DefaultValue
{
get { return "Default String"; }
}
// Optionally override TypedValue
public override void Deal()
{
Console.WriteLine(TypedValue.PadLeft(20));
}
}
class AssetDataFieldFloat : AssetDataFieldType<float>
{
public override object DefaultValue
{
get { return 0; }
}
// Optionally override TypedValue
public override void Deal()
{
Console.WriteLine(TypedValue.ToString("#0.000"));
}
}
Note: this smells like the result of querying an EAV based system. In the same way that meta data is the backbone of this sort of system the code referencing it should strive to know what it is accessing (and thus the types) at compile time. That said if you want to simply display the data this sort of thing is required no matter what.
C# is statically typed so you cannot put 'different things' into the same 'slot' (variable, array location) unless the slot is the right 'shape' to take all of them(1). The only slot currently available in c# for this is object. This will work but will box any value types(2).
In c# 4.0 you can use dynamic, which under the hood will be an object but at least will let you invoke any methods on it you want even if the compiler doesn't think it's legal via object.
If all the types in question share a common interface then you can avoid object and get some useful semantics (say if double Sum(double d) was a meaningful operation for any instance you were dealing with then this could yield useful results. However it sounds like you do not control the types present (and thus stand no chance of getting them to conform to useful interfaces).
If the set of possible types is tractable the technique described below can work but it is still cumbersome.
// boxes if needed
public interface IGeneralValue
{
object Value { get; }
Type GetValueType();
}
public class Value<T> : IGeneralValue
{
public T Value { get; set;}
object IGeneralValue.Value
{
get { return (object)this.Value; }
}
public Type GetValueType()
{
return typeof(T);
}
}
Then you can stay statically typed where possible but if not something similar to your previous code will work.
Asset certainAsset = new Asset(32423);
foreach (IGeneralValue dataField in certainAsset.DataFields)
{
object fieldValue = datafield.Value;
Type fieldType = dataField.GetValueType();
if (typeof(double).Equals(fieldType))
{
double d = ((double)fieldValue);
}
else if (typeof(string).Equals(fieldType))
{
string d = ((string)fieldValue);
}
else if (typeof(whatever).Equals(fieldType))
{
// deal with whatever
}
else
{
// the safe option
throw new NotSupportedException(fieldType +" is not supported!");
}
}
Without unsafe code or unions (only structs) at least.
This has implications not just on performance, you cannot unbox an int as a double for example, despite that conversion working on unboxed instances.

Can I pass parameters by reference in Java?

I'd like semantics similar to C#'s ref keyword.
Java is confusing because everything is passed by value. However for a parameter of reference type (i.e. not a parameter of primitive type) it is the reference itself which is passed by value, hence it appears to be pass-by-reference (and people often claim that it is). This is not the case, as shown by the following:
Object o = "Hello";
mutate(o)
System.out.println(o);
private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!
Will print Hello to the console. The options if you wanted the above code to print Goodbye are to use an explicit reference as follows:
AtomicReference<Object> ref = new AtomicReference<Object>("Hello");
mutate(ref);
System.out.println(ref.get()); //Goodbye!
private void mutate(AtomicReference<Object> ref) { ref.set("Goodbye"); }
Can I pass parameters by reference in
Java?
No.
Why ? Java has only one mode of passing arguments to methods: by value.
Note:
For primitives this is easy to understand: you get a copy of the value.
For all other you get a copy of the reference and this is called also passing by value.
It is all in this picture:
In Java there is nothing at language level similar to ref. In Java there is only passing by value semantic
For the sake of curiosity you can implement a ref-like semantic in Java simply wrapping your objects in a mutable class:
public class Ref<T> {
private T value;
public Ref(T value) {
this.value = value;
}
public T get() {
return value;
}
public void set(T anotherValue) {
value = anotherValue;
}
#Override
public String toString() {
return value.toString();
}
#Override
public boolean equals(Object obj) {
return value.equals(obj);
}
#Override
public int hashCode() {
return value.hashCode();
}
}
testcase:
public void changeRef(Ref<String> ref) {
ref.set("bbb");
}
// ...
Ref<String> ref = new Ref<String>("aaa");
changeRef(ref);
System.out.println(ref); // prints "bbb"
From James Gosling in "The Java Programming Language":
"...There is exactly one parameter passing mode in Java - pass by value - and that keeps things simple.
.."
I don't think you can. Your best option might be to encapsulate the thing you want to pass "by ref" onto another class instance, and pass the (outer) class's reference (by value). If you see what I mean...
i.e. your method changes the internal state of the object it is passed, which is then visible to the caller.
Java is always pass by value.
When you pass a primitive it's a copy of the value, when you pass an object it's a copy of the reference pointer.
Another option is to use an array, e.g.
void method(SomeClass[] v) { v[0] = ...; }
but 1) the array must be initialized before method invoked, 2) still one cannot implement e.g. swap method in this way...
This way is used in JDK, e.g. in java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[]).
Check out my response in: http://stackoverflow.com/a/9324155/1676736
In there I used a simpler version of the wrapper class idea.
I don't like setters/getters as a standard. When there is no reason to bury a field I make it 'public'. Especially in something like this.
However, this would work for all but the primitive, or multi-parameter/type returns:
public class Ref<T> {
public T val;
}
Although, I suppose you could just add more type parameters. But I think that creating an inner static class fit-for-purpose would be easier:
public static class MyReturn {
public String name;
public int age;
public double salary;
}
this would be for use when you don't need it for other reasons.
MyReturn mRtn = new MyReturn();
public void myMethod(final MyReturn mRtn){
mRtn.name = "Fred Smith";
mRtn.age = 32;
mRtn.salary = 100000.00;
}
System.out.println(mRtn.name + " " +mRtn.age + ": $" + mRtn.salary);

Categories

Resources