How can I make an "abstract" enum in a .NET class library? - c#

I'm making a server library in which the packet association is done by enum.
public enum ServerOperationCode : byte
{
LoginResponse = 0x00,
SelectionResponse = 0x01,
BlahBlahResponse = 0x02
}
public enum ClientOperationCode : byte
{
LoginRequest = 0x00,
SelectionRequest = 0x01,
BlahBlahRequest = 0x02
}
That works fine when you're working in your own project - you can compare which enum member is returned (i.e. if (packet.OperationCode == ClientOperationCode.LoginRequest)). However, since this is a class library, the user will have to define its own enum.
Therefore, I have two enums to add as "abstract" - ServerOperationCode and ClientOperationCode. I know it's not possible to implement abstract enums in C#. How would I go doing this?

I like to use static instances on my classes when I need to do this. It allows you to have some default values but also lets it be extensible through the usual means of inheritance and interface implementations:
public abstract class OperationCode
{
public byte Code { get; private set; }
public OperationCode(byte code)
{
Code = code;
}
}
public class ServerOperationCode : OperationCode
{
public static ServerOperationCode LoginResponse = new ServerOperationCode(0x00);
public static ServerOperationCode SelectionResponse = new ServerOperationCode(0x01);
public static ServerOperationCode BlahBlahResponse = new ServerOperationCode(0x02);
public ServerOperationCode(byte code) : base(code) { }
}
public class ClientOperationCode : OperationCode
{
public static ClientOperationCode LoginRequest = new ClientOperationCode(0x00);
public static ClientOperationCode SelectionRequest = new ClientOperationCode(0x01);
public static ClientOperationCode BlahBlahRequest = new ClientOperationCode(0x02);
public ClientOperationCode(byte code) : base(code) { }
}
assuming packet.OperationCode return a byte, you will likely have to implement an == operator for byte. put this code into your abstract OperationCode class.
public static bool operator ==(OperationCode a, OperationCode b)
{
return a.Code == b.Code;
}
public static bool operator !=(OperationCode a, OperationCode b)
{
return !(a == b);
}
this will allow you to have the same check as you showed:
if (packet.OperationCode == ClientOperationCode.LoginRequest)

Why does everyone think that Enums cannot be abstracted?
The class System.Enum IS the abstraction of an enumeration.
You can assign any enumeration value to an Enum, and you can cast it back to the original enumeration or use the name or value.
eg:
This little snippet of code is from a dynamic property collection used in one of my control libraries. I allow properties to be created and accessed through an enumeration value to make it slightly faster, and less human-error
/// <summary>
/// creates a new trigger property.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <param name="name"></param>
/// <returns></returns>
protected virtual TriggerProperty<T> Create<T>(T value, Enum name)
{
var pt = new TriggerProperty<T>(value, OnPropertyChanged, Enum.GetName(name.GetType(), name));
_properties[name.GetHashCode()] = pt;
return pt;
}
I use Enum.GetName(Type, object) to get the name of the enumeration value (to supply a name for the property), and for speed and consistency reasons I use GetHashCode() to return the integer value of the enumeration member (the hash code for an int is always just the int value)
This is an example of the method being called:
public enum Props
{
A, B, C, Color, Type, Region, Centre, Angle
}
public SpecularProperties()
:base("SpecularProperties", null)
{
Create<double>(1, Props.A);
Create<double>(1, Props.B);
Create<double>(1, Props.C);
Create<Color>(Color.Gray, Props.Color);
Create<GradientType>(GradientType.Linear, Props.Type);
Create<RectangleF>(RectangleF.Empty, Props.Region);
Create<PointF>(PointF.Empty, Props.Centre);
Create<float>(0f, Props.Angle);
}

If you mean to say that you want an enum that can be extended by clients of the library, check out my CodeProject article on the topic, Symbols as extensible enums.
Note that in my library, Symbol chooses ID numbers for the "enum values" automatically, since it is designed for use inside a single program rather than for exchanging values on a network. Perhaps it would be possible, however, to alter Symbol.cs to your liking so that clients can assign constant values to symbols.

Create an Enum for LoginResponse, SelectionResponse, etc., but don't specify the values.
Have ServerOperationCode and ClientOperationCode implement a function that, given an integer bytecode, returns the appropriate value from your Enum.
Example:
public enum OperationCode
{
LoginResponse,
SelectionResponse,
BlahBlahResponse
}
public interface IOperationCodeTranslator {
public OperationCode GetOperationCode(byte inputcode);
}
public class ServerOperationCode : IOperationCodeTranslator
{
public OperationCode GetOperationCode(byte inputcode) {
switch(inputcode) {
case 0x00: return OperationCode.LoginResponse;
[...]
}
}
Caveat: since interfaces can't define static functions, ServerOperationCode and ClientOperationCode would only be able to implement a common interface if said function is an instance function. If they don't need to implement a common interface, GetOperationCode can be a static function.
(Apologies for any C# snafus, it's not my first language...)

If there is a database that is shared between your client and server application, then look-up tables may help; the table structure just contain an integer value (ID) and a string (the name), this table can be filled out by either side of your application (the client or the server) and read by the other. You can cache these table (in your code) in a dictionary for quick look-up.
You can also implement the same thing in the app.config file; force the user of your library to set these values in the app.config file which your library can access easily.

I wrote a message switching library with a similar scenario a while back, and I decided to use generics to pass the user-defined enum. The main problem with this is you can't constrain your generic to only enum types, but can only say while T: struct. Someone may instantiate your type with some other primitive type (although, using ints could still be functional, provided they're all unique values. The dictionary will throw an exception if they're not. You could possibly add some additional check using reflection to ensure you pass an enum.
public abstract class DefaultMessageHandler<T> : IMessageHandler<T> where T : struct {
public delegate void MessageHandlerDelegate(IMessage<T> message, IConnection connnection);
private readonly IDictionary<T, MessageHandlerDelegate> messageHandlerDictionary =
new Dictionary<T, MessageHandlerDelegate>();
protected void RegisterMessageHandler(T messageType, MessageHandlerDelegate handler) {
if (this.messageHandlerDictionary.ContainsKey(messageType))
return;
else this.messageHandlerDictionary.Add(messageType, handler);
}
protected void UnregisterMessageHandler(T messageType) {
if (this.messageHandlerDictionary.ContainsKey(messageType))
this.messageHandlerDictionary.Remove(messageType);
}
protected virtual void HandleUnregisteredMessage(IMessage<T> message, IConnection connection) {
}
void IMessageHandler<T>.HandleMessage(IMessage<T> message, IConnection connection) {
if (this.messageHandlerDictionary.ContainsKey(message.MessageType))
this.messageHandlerDictionary[message.MessageType].Invoke(message, connection);
else HandleUnregisteredMessage(message, connection);
}
}
Given your example scenario, you'd just subclass it like this.
public sealed class ServerOperationHandler : DefaultMessageHandler<ServerOperationCode> {
public ServerOperationHandler() {
this.RegisterMessageHandler(ServerOperationCode.LoginResponse, this.HandleLoginResponse);
this.RegisterMessageHandler(ServerOperationCode.SelectionResponse, this.HandleSelectionResponse);
}
private void HandleLoginResponse(IMessage<ServerOperationCode> message, IConnection connection) {
//TODO
}
private void HandleSelectionResponse(IMessage<ServerOperationCode> message, IConnection connection) {
//TODO
}
}

How about using static Dictionary and a virtual method to retrieve the static dictionaries in the inherited classes?
Like the follow for your case:
public abstract class Operation
{
protected abstract Dictionary<string, int> getCodeTable();
public int returnOpCode(string request){ return getCodeTable()[request]; }
}
public class ServerOperation : Operation
{
Dictionary<string, int> serverOpCodeTable = new Dictionary<string, int>()
{
{"LoginResponse", 0x00,},
{"SelectionResponse", 0x01},
{"BlahBlahResponse", 0x02}
};
protected override Dictionary<string, int> getCodeTable()
{
return serverOpCodeTable;
}
}
public class ClientOperation : Operation
{
Dictionary<string, int> cilentOpCodeTable = new Dictionary<string, int>()
{
{"LoginResponse", 0x00,},
{"SelectionResponse", 0x01},
{"BlahBlahResponse", 0x02}
};
protected override Dictionary<string, int> getCodeTable()
{
return cilentOpCodeTable;
}
}

Related

c# virtual static members

Yeah, I know there aren't any virtual static members in c#, but I have a problem where they would be really helpful and I can't see a good way to proceed.
I've got a standard kind of system where I send packets of data over a communication channel and get back responses. The communication system needs to know how many bytes of response to wait for, and the length of the response is fixed for each command type, so I have this code defined:
public abstract class IPacket
{
public abstract int ReceiveLength { get; }
public abstract byte[] DataToSend();
}
public class Command1 : IPacket
{
public override int ReceiveLength { get { return 3; } }
public Command1() { }
}
public class Command2 : IPacket
{
public override int ReceiveLength { get { return DataObject.FixedLength; } }
public Command2(int x) { }
}
public class Command3 : IPacket
{
static DataHelperObject Helper;
public override int ReceiveLength { get { return Helper.DataLength(); } }
static Command3()
{
Helper = new DataHelperObject();
}
public Command3(really long list of parameters containing many objects that are a pain to set up) { }
}
Notice that in each case, ReceiveLength is a fixed value - sometimes it's a simple constant (3), sometimes it's a static member of some other class (DataObject.FixedLength) and sometimes it's the return value from a member function of a static member (Helper.DataLength()) but it's always a fixed value.
So that's all good, I can write code like this:
void Communicate(IPacket packet)
{
Send(packet.DataToSend());
WaitToReceive(packet.ReceiveLength);
}
and it works perfectly.
But now I would like to output a summary of the packets. I want a table that shows the command name (the class name) and the corresponding ReceiveLength. I want to be able to write this (pseudo)code:
foreach (Class cls in myApp)
{
if (cls.Implements(IPacket))
{
Debug.WriteLine("Class " + cls.Name + " receive length " + cls.ReceiveLength);
}
}
But of course ReceiveLength requires an object.
I don't think I can use attributes here, c# won't let me say:
[PacketParameters(ReceiveLength=Helper.DataLength())]
public class Command3 : IPacket
{
static DataHelperObject Helper;
static Command3()
{
Helper = new DataHelperObject();
}
public Command3(really long list of parameters containing many objects that are a pain to set up) { }
}
because custom attributes are created at compile time (right?), long before the static constructor gets called.
Constructing objects of each type isn't particularly pleasant (pseudocode again):
foreach (Class cls in myApp)
{
IPacket onePacket;
if (cls is Command1)
onePacket = new Command1();
else if (cls is Command2)
onePacket = new Command2(3);
else if (cls is Command3)
{
Generate a bunch of objects that are a pain to create
onePacket = new Command3(those objects);
}
Debug.WriteLine("Class " + cls.Name + " receive length " + onePacket.ReceiveLength);
}
I need ... a virtual static property.
One solution would be to throw all compile-time safety over board and simply use reflection to access your static property like so: http://fczaja.blogspot.ch/2008/07/accessing-static-properties-using-c.html
Alternatively, you could separate out that information into a "PaketSizeManager" type which would simply have either the above-mentioned Dictionary or some switch-case statement plus some neat way to access this information from the outside, as in a public int GetSize(Type t){ .../* use dictionary or switch-case here */... } method. That way you would have encapsulated the size aspect of all your entities into a separate class.
Just make a public static CommandX.Length property, have it return what your ReceiveLength property is now, then have ReceiveLength refer to it. To get the best of both worlds, first you need both worlds.

Generic class to store variable content

I want to create a structure to store data consumed from a Web Service with the followind specs:
Response:
Field 1 - InstructionType: Can be 1 (PreferredDay), 2 (SVP), 3 (Neighbour)
Field 2: Some variable data. Its type depends on Field 1. So if:
Field 1 == 1 then Field 2 type will be of DateTime (dd.MM.yyyy)
Field 1 == 2 then Field 2 type will be of type string.
Field 1 == 3 then Field 2 type will be of type string
So, I started up with the following enum:
public enum InstructionType
{
None = 0,
PreferredDay = 1,
ServicePoint = 2,
Neighbour = 3
}
And the generic class:
public abstract class Instruction<T>
{
public InstructionType Type { get; private set; }
public T Data { get; private set; }
public Instruction(InstructionType type, T data)
{
this.Type = type;
this.Data = data;
}
}
and concrete classes:
public class PreferredDayInstruction : Instruction<DateTime>
{
public PreferredDayInstruction(DateTime data)
: base (InstructionType.PreferredDay, data) {}
}
public class ServicePointInstruction: Instruction<string>
{
public ServicePointInstruction(string data)
: base (InstructionType.ServicePoint, data) {}
}
public class NeughbourInstruction: Instruction<string>
{
public NeughbourInstruction(string data)
: base (InstructionType.Neighbour, data) {}
}
When parsing web service's response created a public function:
public Instruction DeliveryInstruction() <---Compiler error here "Instruction"
{
if (resultFromWebservice.Field1 == 1)
return new PreferredDayInstruction((DateTime)Field2);
if (resultFromWebservice.Field1 == 2)
return new ServicePointInstruction(Field2);
if (resultFromWebservice.Field1 == 3)
return new NeighbourInstruction(Field2);
}
and here is the problem. Can't return objects of generic type.
Tried with with Interface, factories, and other stuff, but allways with the same problem. So, is there any way to archieve this? maybe it's not possible or maybe is so easy I can't see now. Thanks in advance.
UPDATE:
Compiler error on BOLD Instruction
Error 1 Using the generic type 'NAMESPACE.Instruction' requires '1' type arguments
I forgot..I'm using .NET 3.5
It looks like you may be starting off with an intent to use generics rather than using them because you've identified a need. Often (not always) when that gets difficult it's because it didn't actually fit what you were trying to do.
What seems odd in this case is that you have both a generic type and an enum to indicate the type. This is likely to cause you a few problems.
First it looks like you're trying to create a one-size-fits all class to model different types of behaviors. That will start off confusing and get more confusing. Think of most classes that are part of the .NET framework, and imagine what would happen if they had properties like Field1 and Field2, and you couldn't tell from looking at them what they were for. And in one method they're used for one thing, but in a another case they mean something else.
Also, if you're trying to put different types of instructions in one class, that suggests that maybe you're going to try passing them all to one method, and that method figures out what to do, and maybe calls other methods. (I'm guessing that because of the enum. Perhaps you're going to handle the input differently depending on which value it contains.) That one method will get really hard to maintain.
I'd recommend waiting on generics until you're sure you need them. And if you have different types of instructions you're likely better off writing a different class for each one with the properties it needs and names that describe them, and writing methods for each of them to do what they need to do. If you need lots of classes, make lots of them.
It's very easy to fall into the trap of trying to solve problems that don't exist, like how do I write one class that covers a bunch of different needs. The answer usually that you don't need to. You'll get better results from writing more classes that each do fewer things.
Believe me that I tried to do my best to explain what was my problem and what I needed in order to solve it. In a nutshell, the question was quite simple. Is this possible or not? So, is there a way to return a common type for these 3 classes? Answer is no, as they don't share any root. They all derive from Instruction, but aren't compatible each other. That's what I learned from this experience.
As another example, lets take another .NET framework's generic type.
public class ListOfString : List<string> { }
public class ListOfInt : List<int> { }
public class ListOfDecimal : List<decimal> { }
And, in another place of the application, get a method who returns one of this List based on some logic:
public class Logic
{
public List<> GetList(Type t) <----This can't be done
{
if (t == typeof(string))
return new ListOfString();
if (t == typeof(int))
return new ListOfInt();
if (t == typeof(decimal))
return new ListOfDecimal();
else return null;
}
}
Please, keep in mind that this is just a stupid sample just to show what's the point of this post.
By the way, in the case of List the following can be done, because there is a non generic different version of IList:
public IList GetList(Type t)
{
....
}
But I can't think of a way to do this in my particular case.
Anyway, I finally followed another approach. I reallized that what I really wanted is to ensure Data property is valid. If it it's supposed to be a date there, ensure date is valid. Is it a string, ensure it has the right length or whatever rule it must follow.
So this is the final solution:
The enum:
public enum InstructionType
{
None = 0,
PreferredDay = 1,
ServicePoint = 2,
Neighbour = 3
}
The base class:
public abstract class Instruction
{
public InstructionType Type { get; private set; }
public string Data { get; private set; } <---Type String
public Instruction(InstructionType type, string data)
{
this.Type = type;
this.Data = IsValid(data) ? data : string.Empty;
}
public abstract bool IsValid(string data); <--the rule.
}
The concrete classes:
public class PreferredDayInstruction : Instruction
{
public PreferredDayInstruction(string date)
: base(InstructionType.PreferredDay, date) { }
public override bool IsValid(string data)
{
string[] formats = {"dd.MM.yyyy", "d.MM.yyyy",
"dd.MM.yy", "d.MM.yy"};
try
{
data = data.Replace('/', '.').Replace('-', '.');
var dateparts = data.Split('.');
DateTime date = new DateTime(Convert.ToInt32(dateparts[2]),
Convert.ToInt32(dateparts[1]),
Convert.ToInt32(dateparts[0]));
//DateTime.ParseExact(data, formats, null, System.Globalization.DateTimeStyles.AssumeLocal);
return true;
}
catch (Exception)
{
return false;
}
}
}
public class ServicePointInstruction : Instruction
{
public ServicePointInstruction(string data)
: base (InstructionType.ServicePoint, data) { }
public override bool IsValid(string data)
{
return ServicePointBarcodeValidator.Validate(data);
}
}
public class NeighbourInstruction : Instruction
{
public NeighbourInstruction(string data) :
base(InstructionType.Neighbour, data) { }
public override bool IsValid(string data)
{
return data.Length <= 70;
}
}
A factory class, who's responsability is to create and return the correct object based on the enum:
public static class DeliveryInstructionFactory
{
public static Instruction Create(int type, string data)
{
return Create((InstructionType)type, data);
}
public static Instruction Create(InstructionType type, string data)
{
switch (type)
{
case InstructionType.PreferredDay:
return new PreferredDayInstruction(data);
case InstructionType.ServicePoint:
return new ServicePointInstruction(data);
case InstructionType.Neighbour:
return new NeighbourInstruction(data);
default:
return null;
}
}
}
And finally, as now all of they share the same root, object can be created on webservice's response parser:
public Instruction DeliveryInstruction()
{
try
{
int instructionCode = int.Parse(observation.Substring(173,2));
string instructionData = observation.Substring(175, 10);
return DeliveryInstructionFactory.Create(instructionCode, instructionData); }
catch (Exception ex)
{
Log.Error("[ValidationBarcodeResponse] DeliveryInstructions aren't in the correct format", ex);
return null;
}
}
Hope this now fits on a Minimal, Complete, and Verifiable example

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

Is there a generic collection that I can access the elements through the indexer by string key and by index?

I want to declare a generic collection of objects and be able to access them through the indexer either by a key string value or by index. How do I do this? Is there is an out of the box .Net class that doesn't require sub-classing?
class Program
{
static void Main(string[] args)
{
System.Collections.Generic.WhatKindOfCollection<PageTab> myPageTabs
= new System.Collections.Generic.WhatKindOfCollection<PageTab>();
PageTab pageTab1 = new PageTab();
pageTab1.ID = "tab1";
myPageTabs.Add(pageTab1);
myPageTabs.Add(new PageTab("tab2"));
myPageTabs[0].label = "First Tab";
myPageTabs["tab2"].label = "Second Tab";
}
public class PageTab
{
public PageTab(string id)
{
this.ID = id;
}
public PageTab() { }
//Can I define ID to get the key property by default?
public string ID { get; set; }
public string label { get; set; }
public bool visible { get; set; }
}
}
It looks like you're looking for something derived from System.Collections.ObjectModel.KeyedCollections.
I don't think that the specific class you're looking for exists in the .NET framework, so you'll probably have to subclass it yourself.
KeyedCollection is a base class for objects where the key is part of the object. This means that when you access it with an integer index, you'll get back the original object instead of a KeyValueCollection.
It's been a while since I've used it, but I don't remember it being too difficult.
Edit: Another code option for you. It was easier than I remember:
public class MyKeyedCollection<TKey, TItem> : KeyedCollection<TKey, TItem>
{
public MyKeyedCollection(Func<TItem, TKey> keyFunction)
{
_keyFunction = keyFunction;
}
private Func<TItem, TKey> _keyFunction;
protected override TKey GetKeyForItem(TItem item)
{
return _keyFunction(item);
}
}
To use:
var myPageTabs = new MyKeyedCollection<String, PageTab>(i => i.ID);
Or pre-LINQ:
public class MyKeyedCollection<TKey, TItem> : KeyedCollection<TKey, TItem>
{
public MyKeyedCollection(String keyProperty)
{
_keyProperty = keyProperty;
}
private String _keyProperty;
protected override TKey GetKeyForItem(TItem item)
{
return (TKey)item.GetType().GetProperty(_keyProperty).GetValue(item, null);
}
}
and
MyKeyedCollection<String, PageTab> myPageTabs = new MyKeyedCollection<String, PageTab>("ID");
This is effectively the OrderedDictionary class. However, it is, unfortunately, not a generic class, so you'd have to include casts, or wrap it in your own collection type.
There is no generic equivelent in the base class libraries, though KeyedCollection<T,U> provides the base class infrastructure to implement your own version.
The simplest alternative is just to maintain two collections - a Dictionary<string, PageTab> and a List<PageTab>. When you create your items, you can add it to both collections, and access via the appropriate one. Since PageTab is a class, the extra overhead is minimal (since you're just storing object references). This could also be easily wrapped into a class:
public class IndexedDictionary<T, U>
{
private Dictionary<T,U> dictionary = new Dictionary<T,U>();
private List<U> list = new List<U>();
public void Add(T key, U value)
{
list.Add(value);
dictionary.Add(key, value);
}
public U this[int index]
{
get { return list[index]; }
}
public U this[T key]
{
get { return dictionary[key]; }
}
}
Granted, you'd potentially want to implement some appropriate interfaces as well (such as IEnumerable<U>), but the above would accomplish your goals as listed in the question.
Why don't you use a dictionary?
Dictionary<string, PageTab> myDictionary = new Dictionary<string, PageTab>();
myDictionary.Add("tab1", new PageTab("tab1"));
PageTab myPageTab = myDictionary["tab1"];
EDIT
To avoid typing the key twice (once as dictionary key and once in the constructor) you could extend the dictionary. Create the following class in the toplevel of your namespace:
public static class Extensions
{
public static void AddPageTab(this Dictionary<string, PageTab> mydict, PageTab pt)
{
mydict.Add(pt.ID, pt);
}
}
And you call simple add the PageTab like this:
myDictionary.AddPageTab(new PageTab("tab1"));

.Net interface for a known return type, but unknown type/number of parameters

Is there a way to specify in an interface a known return type, but unknown number/type of parameters.
The reason I am asking is that I am using Windows Azure Table Storage and each table will have different Partition and Row keys with different input values.
I am creating a ITableOperations interface the code will be something like:
interface ITableOperations<T>
where T : Azure.AzureTableEntity
{
// Key specification
string PartitionKey(/* ? What should go here */);
// Key specification
string RowKey(/* ? What should go here */);
}
And the item table... For another table, the input params would be different
public class ScheduledItem : ITableOperations<ScheduledPostEntity>
{
public string PartitionKey(Guid userGuid)
{
return userGuid.ToString();
}
public string RowKey(DateTime dateScheduled)
{
return dateScheduled.ReverseTicks();
}
}
You could try having a very generic interface. For example:
interface ITableOperations<T, P, R>
where T : Azure.AzureTableEntity
{
string PartitionKey(P partitionKey);
string RowKey(R rowKey);
}
Then your implementation could be:
public class ScheduledItem : ITableOperations<ScheduledPostEntity, Guid, DateTime>
{
public string PartitionKey(Guid userGuid)
{
return userGuid.ToString();
}
public string RowKey(DateTime dateScheduled)
{
return dateScheduled.ReverseTicks();
}
}
EDIT:
Looking at some of your comments since I originally wrote this answer, you could come at it from a different angle. The PartitionKey and RowKey won't change on your object once it has been created, so I'd almost take these particular functions out of this class and move it to the constructors of the classes that inherit from AzureTableEntity. e.g.
public class ScheduledPostEntity : Azure.AzureTableEntity
{
private Guid _userGuid;
private DateTime _dateScheduled;
public ScheduledPostEntity()
{
// Needed for deserialisation from Azure Table Storage
}
public ScheduledPostEntity(Guid userGuid, DateTime dateScheduled)
{
_userGuid = userGuid;
_dateScheduled = dateScheduled;
}
public string PartitionKey
{
get { return _userGuid.ToString(); }
set { _userGuid = Guid.Parse(value); }
}
public string RowKey
{
get { return _dateScheduled.ReverseTicks(); }
set { _dateScheduled = value.FromReverseTicks(); }
}
// These are functions to avoid them being saved as additional properties
// in Azure Table Storage. Sometimes you can get away with them being
// read only properties, but it depends on the type.
public DateTime DateScheduled()
{
return _dateScheduled;
}
public Guid UserGuid()
{
return _userGuid;
}
}
This has the advantage that whenever you create on of these objects, you know minimum requirements to save the object. It also stops you from messing with things that will change your PK and RK.
C# supports multiple parameter in the form of an array by using the params keyword.
You could do this:
interface ITableOperations<T>
where T : Azure.AzureTableEntity
{
// Key specification
string PartitionKey(params object[] data);
// Key specification
string RowKey(params object[] data);
}
If you already know the alternatives of parameters, then you can use overload.
Lets say you have a method that can either receive a string or a Guid or both, you could do this:
string PartitionKey(Guid guid);
string PartitionKey(string str);
string PartitionKey(Guid guid, string str);
If you are using C# 4, then you can use optional parameters:
string PartitionKey(Guid guid = default(Guid), string str = null);
You could define one parameter, which would be an array. This array would contain name/value pairs and could have as many as you need. I think this would give you the flexibility you're looking for.
This still won't show you the proper list of parameters for DoStuff (you'll just see params object[]) but it's about as flexible as you'll get. Note that I've implemented the method explicitly in the implementing class so you don't see it in Intellisense if "foo" is declared as a Foo rather than an IFoo.
class Program
{
static void Main(string[] args)
{
IFoo foo = new Foo();
foo.DoStuff(Guid.NewGuid());
}
}
public interface IFoo
{
void DoStuff(params object[] args);
}
public class Foo : IFoo
{
public void DoStuff(Guid arg)
{
}
void IFoo.DoStuff(params object[] args)
{
if (args.Length != 1) throw new ArgumentException("args");
if (args[0].GetType() != typeof(Guid)) throw new ArgumentException("args");
DoStuff((Guid)args[0]);
}
}

Categories