Can generics improve this design? - c#

The PartyRoleConstraints class in the model below (on the right) is the subject of this question.
The idea is that when a client tries to associate a Party with a RoleType, the RoleType sees if it has any Constraints that should prevent a given Party from being associated. A Party is a supertype for both Person and Organization.
Here is the totally generic interface I am after:
public interface IRoleConstraint<in T>
{
Func<T, bool> IsSatisfied { get; }
string UnsatisfiedDescription { get; }
bool CanAddRole(T instance);
}
A common constraint would be by Type. So if I have role type of "husband" then I want to make sure the Party instance is a Person. Here is some implementation and a test case proving I can do this:
public class RoleConstraint<T> : IRoleConstraint<T>
{
public RoleConstraint(Func<T, Boolean> isSatisfied, string unsatisfiedDescription) {
if (isSatisfied == null) throw new ArgumentNullException("isSatisfied");
if (unsatisfiedDescription == null) throw new ArgumentNullException("unsatisfiedDescription");
IsSatisfied = isSatisfied;
UnsatisfiedDescription = unsatisfiedDescription;
}
public Func<T, bool> IsSatisfied { get; protected set; }
public string UnsatisfiedDescription { get; protected set; }
public bool CanAddRole(T instance) { return IsSatisfied.Invoke(instance); }
}
public class PartyRoleConstraint : RoleConstraint<Party>
{
public PartyRoleConstraint(Func<Party, bool> isSatisfied, string unsatisfiedDescription) : base(isSatisfied, unsatisfiedDescription) { }
}
public class PartyRoleConstrainedToType<TRequired> : PartyRoleConstraint where TRequired : Party
{
private static readonly string _unsatisfiedDescription
= string.Format("This role requires a Party instance to be a {0}", typeof(TRequired).Name);
private static readonly Func<Party, bool> _isSatisfied = instance => instance.GetType().Equals(typeof(TRequired));
public PartyRoleConstrainedToType() : base(_isSatisfied, _unsatisfiedDescription) { }
}
[Test]
public void Constraints_IfTypeConstraint_and_InstanceDoesNotMatch_False()
{
var sony = new Organization("Sony Corporation");
var constraint = new PartyRoleConstrainedToType<Person>();
_husbandRoleType.AddConstraint(constraint);
Assert.That(_husbandRoleType.CanAddRole(sony), Is.False);
}
The problem I am hitting is if I want to set up a rule based on an attribute of a subtype of Party. For example, I want the gender of the husband to be Male. I can do this with a cast, as:
[Test]
public void Constraints_IfConstraintConditionIsNotMet_False()
{
_husbandRoleType.AddConstraint(new PartyRoleConstrainedToType<Person>());
Assert.That(_husbandRoleType.CanAddRole(_arthur), Is.True);
//**** here is the cast **** //
var mustBeMale = new PartyRoleConstraint(p => ((Person)p).Gender == Gender.Male, "the husband must be male.");
_husbandRoleType.AddConstraint(mustBeMale);
Assert.That(_husbandRoleType.CanAddRole(_arthur), Is.False);
_arthur.Gender = Gender.Male;
Assert.That(_husbandRoleType.CanAddRole(_arthur), Is.True);
}
The question (finally!) is: can I use generics to avoid that cast, and if so, how?

Yes, you can get rid of the cast, but you will have to specify "Person" somewhere. It's hard to propose a "best place" to do so, without knowing more about your requirements and constraints. One option would be something like:
var mustBeMale = PartyRoleConstraint.For<Person>( p => p.Gender == ...);
Another option would be to tweek PartyRoleConstrainedToType to allow further restrictions. And example might look like this:
var combinedConstraint = new PartyRoleConstrainedToType<Person>().MustSatisfy(p => p.Gender == ...);
As said before: You will have to specify Person somewhere, but there a different options to create a nice syntax. What nice means, depends on your requirements and use cases.

Related

How to store a list of different generic things in C#

Say for example I have this base class
class Mangler<TInput, TOutput>
{
}
And then I make a couple of derived classes
class StringToBytesMangler : Mangler<string, byte[]>
{
}
class IntToGuidMangler : Mangler<int, Guid>
{
}
How do I store a collection of Mangler<TInput, TOutput> where TInput and TOutput may be different at any given time?
i.e.
List<Mangler<?, ?>> list = new List<Mangler<?, ?>>();
list.Add(new StringToBytesMangler());
list.Add(new IntToGuidMangler());
Is this possible?
You need a non-generic Mangler base class.
List<Mangler> list = new List<Mangler>();
list.Add(new StringToBytesMangler());
list.Add(new IntToGuidMangler());
Of course, this means you also need to have non-generic versions of the methods that depend on TInput or TOutput.
If I understood the question correctly, this is not possible the way you tried it. The types StringToBytesMangler and IntToGuidMangler do not derive from the same type. You could introduce a shared base type, but I recommend reconsidering the design - even if they could be stored in the same collection, they would syntactically have nothing in common (at least it isn't shown in the question).
The whole idea behind generics is to have generic code so type of that class can be treated the same. From what you have posted, it is not easy to see what generic code you have.
Below I have a class that has some generic code:
class Mangler<TInput, TOutput>
where TInput: ITInput
where TOutput: ITOutput {
public TInput Input { get; set; }
public TOutput Output { get; set; }
public bool IsInputAGuid() {
if (Guid.Parse(this.Input.SomeThing) == this.Output.SomeGuid ) {
return true;
}
return false;
}
}
You can see in the above class, when it parses a string to a Guid from this.Input.Something and then it performs == on it with this.Ouput.SomeGuid, the compiler is happy because we have made the constraint that TInput must implement the interface ITInput so the compiler knows this line will work and Input will have Something as a string property:
Guid.Parse(this.Input.SomeThing)
The compiler does not care what the concrete type is so long as Something is available. It is the same idea for TOuput but the compiler expects that it implements ITOutput so it expects a Guid in SomeGuid. This is why the compiler is happy to parse a string to a guid and then perform the == operator on it with another thing which is also a Guid.
Here are the interfaces and some classes which implement them:
internal interface ITInput {
string SomeThing { get; set; }
}
internal interface ITOutput {
Guid SomeGuid { get; set; }
}
internal class AnotherInput : ITInput {
public string SomeThing { get; set; }
}
internal class SomeInput : ITInput {
public string SomeThing { get; set; }
}
internal class SomeOutput : ITOutput {
public Guid SomeGuid { get; set; }
}
internal class SomeOtherOutput : ITOutput {
public Guid SomeGuid { get; set; }
}
Finally, here is the usage where we can treat these generically:
var manglers = new List<Mangler<ITInput, ITOutput>>();
manglers.Add( new Mangler<ITInput, ITOutput>
{ Input = new SomeInput(), Output = new SomeOutput() } );
manglers.Add( new Mangler<ITInput, ITOutput>
{ Input = new AnotherInput(), Output = new SomeOutput() } );
foreach( var thisMangler in manglers ) {
var input = thisMangler.Input;
var output = thisMangler.Output;
var success = thisMangler.IsInputAGuid();
}
You can see in the foreach regardless of the concrete type, we can call Input, Output and IsInputAGuid() on all of them.
So in your code find what code is generic and then apply the above technique to it. You can either use interfaces or a base class for your constraints.

Emulating F# `with` keyword in C#

Is there a way to emulate F#'s with keyword in C#? I know it will likely not be as elegant, but I'd like to know if there's any way to handle creating new immutable copies of data structures.
Records in F# are detailed here.
Here's an example of what I'm trying to do. We'll create "immutable" views of data via interfaces, while maintaining mutability in concrete classes. This lets us mutate locally (while working) and then return an immutable interface. This is what we're handling immutability in C#.
public interface IThing
{
double A { get; }
double B { get; }
}
public class Thing : IThing
{
double A { get; set; }
double B { get; set; }
}
However, when it comes time to make a change to the data, it's not very type (or mutability!) safe to cast it back and forth, and it's also a real pain to manually translate each property of the class into a new instance. What if we add a new one? Do I have to go track down each manipulation? I don't want to create future headache when I really only need what I had before, but with [some change].
Example:
// ...
IThing item = MethodThatDoesWork();
// Now I want to change it... how? This is ugly and error/change prone:
IThing changed = new Thing {
A = item.A,
B = 1.5
};
// ...
What are sound strategies for accomplishing this? What have you used in the past?
As there is no syntactic sugar I am aware of you'll have to either:
do it by hand (see below)
use some reflection/automapper (not a fan of this)
use some AOP techniques (neither a fan of those)
At least this is what I can think of right now.
I don't think the last two are a good idea because you bring on the big machinery to solve a very easy problem.
Yes when you have thousands of data-structures you might rethink this, but if you only have a couple of them I would not use it.
So what's left is basically smart-constructors and stuff like this - here is a simple example of how you could do it (note that you don't really need all of this - pick and choose) - it's basically missusing null/nullable to look for what you need - better options to this might be overloads or something like an Option<T> data-type but for now I think you get it:
class MyData
{
private readonly int _intField;
private readonly string _stringField;
public MyData(int intField, string stringField)
{
_intField = intField;
_stringField = stringField;
}
public MyData With(int? intValue = null, string stringValue = null)
{
return new MyData(
intValue ?? _intField,
stringValue ?? _stringField);
}
// should obviously be put into an extension-class of some sort
public static MyData With(/*this*/ MyData from, int? intValue = null, string stringValue = null)
{
return from.With(intValue, stringValue);
}
public int IntField
{
get { return _intField; }
}
public string StringField
{
get { return _stringField; }
}
}
To add to Carsten's correct answer, there's no way to do this in C# because it's not in the language. In F#, it's a language feature, where succinct record declaration syntax expands to quite a bit of IL. C# doesn't have that language feature (yet).
This is one of the reasons I no longer like to work in C#, because there's too much overhead compared to doing the same thing in F#. Still, sometimes I have to work in C# for one reason or the other, and when that happens, I bite the bullet and write the records by hand.
As an example, the entire AtomEventSource library is written in C#, but with immutable records. Here's an abbreviated example of the AtomLink class:
public class AtomLink : IXmlWritable
{
private readonly string rel;
private readonly Uri href;
public AtomLink(string rel, Uri href)
{
if (rel == null)
throw new ArgumentNullException("rel");
if (href == null)
throw new ArgumentNullException("href");
this.rel = rel;
this.href = href;
}
public string Rel
{
get { return this.rel; }
}
public Uri Href
{
get { return this.href; }
}
public AtomLink WithRel(string newRel)
{
return new AtomLink(newRel, this.href);
}
public AtomLink WithHref(Uri newHref)
{
return new AtomLink(this.rel, newHref);
}
public override bool Equals(object obj)
{
var other = obj as AtomLink;
if (other != null)
return object.Equals(this.rel, other.rel)
&& object.Equals(this.href, other.href);
return base.Equals(obj);
}
public override int GetHashCode()
{
return
this.Rel.GetHashCode() ^
this.Href.GetHashCode();
}
// Additional members removed for clarity.
}
Apart from the overhead of having to type all of this, it's also been bothering me that if you're doing (dogmatic) Test-Driven Development (which you don't have to), you'd want to test these methods as well.
Using tools like AutoFixture and SemanticComparison, though, you can make it somewhat declarative. Here's an example from AtomLinkTests:
[Theory, AutoAtomData]
public void WithRelReturnsCorrectResult(
AtomLink sut,
string newRel)
{
AtomLink actual = sut.WithRel(newRel);
var expected = sut.AsSource().OfLikeness<AtomLink>()
.With(x => x.Rel).EqualsWhen(
(s, d) => object.Equals(newRel, d.Rel));
expected.ShouldEqual(actual);
}
Here, it's still relatively verbose, but you can easily refactor this to a generic method, so that each test case becomes a one-liner.
It's still a bother, so even if you're writing most of your code in C#, you might consider defining your immutable types in a separate F# library. Viewed from C#, F# records look like 'normal' immutable classes like AtomLink above. Contrary to some other F# types like discriminated unions, F# records are perfectly consumable from C#.
Here is my attempt at emulating immutable mutations in C# via concrete classes. Some magic via generics, which includes type safety!
class Program
{
static void Main(string[] args)
{
var r = new Random();
// A new class item
IDataItem item = new DataItem
{
A = r.NextDouble(),
B = r.NextDouble(),
C = r.NextDouble(),
D = r.NextDouble()
};
// Type hinting here helps with inference
// The resulting `newItem` is an "immutable" copy of the source item
IDataItem newItem = item.With((DataItem x) =>
{
x.A = 0;
x.C = 2;
});
// This won't even compile because Bonkers doesn't implement IDataItem!
// No more casting madness and runtime errors!
IBonkers newItem2 = item.With((Bonkers x) => { /* ... */ });
}
}
// A generic record interface to support copying, equality, etc...
public interface IRecord<T> : ICloneable,
IComparable,
IComparable<T>,
IEquatable<T>
{
}
// Immutable while abstract
public interface IDataItem : IRecord<IDataItem>
{
double A { get; }
double B { get; }
double C { get; }
double D { get; }
}
// Mutable while concrete
public class DataItem : IDataItem
{
public double A { get; set; }
public double B { get; set; }
public double C { get; set; }
public double D { get; set; }
public object Clone()
{
// Obviously you'd want to be more explicit in some cases (internal reference types, etc...)
return this.MemberwiseClone();
}
public int CompareTo(object obj)
{
// Boilerplate...
throw new NotImplementedException();
}
public int CompareTo(IDataItem other)
{
// Boilerplate...
throw new NotImplementedException();
}
public bool Equals(IDataItem other)
{
// Boilerplate...
throw new NotImplementedException();
}
}
// Extension method(s) in a static class!
public static class Extensions
{
// Generic magic helps you accept an interface, but work with a concrete type
// Note how the concrete type must implement the provided interface! Type safety!
public static TInterface With<TInterface, TConcrete>(this TInterface item, Action<TConcrete> fn)
where TInterface : class, ICloneable
where TConcrete : class, TInterface
{
var n = (TInterface)item.Clone() as TConcrete;
fn(n);
return n;
}
}
// A sample interface to show type safety via generics
public interface IBonkers : IRecord<IBonkers> { }
// A sample class to show type safety via generics
public class Bonkers : IBonkers
{
public object Clone()
{
throw new NotImplementedException();
}
public int CompareTo(object obj)
{
throw new NotImplementedException();
}
public int CompareTo(IBonkers other)
{
throw new NotImplementedException();
}
public bool Equals(IBonkers other)
{
throw new NotImplementedException();
}
}

Type safe way to return values from a scripting language in C#

I have been working on a small mathematical scripting engine (or DSL, if you prefer). Making it for fun, its nothing serious. In any case, one of the features I want is the ability to get results from it in a type safe manner. The problem is that there are 5 different types that it can return.
Number, bool, Fun, FunN and NamedValue. There is also AnyFun which is a abstract base class for Fun and FunN. The difference between Fun and FunN is that Fun only takes one argument, while FunN takes more then one argument. Figured it was common enough with one argument to warrant a separate type (could be wrong).
At the moment, I am using a wrapper type called Result and a class called Matcher to accomplish this (inspired by pattern matching in languages like F# and Haskell). It basically looks like this when you use it.
engine.Eval(src).Match()
.Case((Number result) => Console.WriteLine("I am a number"))
.Case((bool result) => Console.WriteLine("I am a bool"))
.Case((Fun result) => Console.WriteLine("I am a function with one argument"))
.Case((AnyFun result) => Console.WriteLine("I am any function thats not Fun"))
.Do();
This is my current implementation. It is rigid, though. Adding new types is rather tedious.
public class Result
{
public object Val { get; private set; }
private Callback<Matcher> _finishMatch { get; private set; }
public Result(Number val)
{
Val = val;
_finishMatch = (m) => m.OnNum(val);
}
public Result(bool val)
{
Val = val;
_finishMatch = (m) => m.OnBool(val);
}
... more constructors for the other result types ...
public Matcher Match()
{
return new Matcher(this);
}
// Used to match a result
public class Matcher
{
internal Callback<Number> OnNum { get; private set; }
internal Callback<bool> OnBool { get; private set; }
internal Callback<NamedValue> OnNamed { get; private set; }
internal Callback<AnyFun> OnAnyFun { get; private set; }
internal Callback<Fun> OnFun { get; private set; }
internal Callback<FunN> OnFunN { get; private set; }
internal Callback<object> OnElse { get; private set; }
private Result _result;
public Matcher(Result r)
{
OnElse = (ignored) =>
{
throw new Exception("Must add a new exception for this... but there was no case for this :P");
};
OnNum = (val) => OnElse(val);
OnBool = (val) => OnElse(val);
OnNamed = (val) => OnElse(val);
OnAnyFun = (val) => OnElse(val);
OnFun = (val) => OnAnyFun(val);
OnFunN = (val) => OnAnyFun(val);
_result = r;
}
public Matcher Case(Callback<Number> fn)
{
OnNum = fn;
return this;
}
public Matcher Case(Callback<bool> fn)
{
OnBool = fn;
return this;
}
... Case methods for the rest of the return types ...
public void Do()
{
_result._finishMatch(this);
}
}
}
The thing is that I want to add more types. I want to make so functions can return both numbers and bools, and change Fun to Fun< T >, where T is the return type. This is actually where the main problem lies. I have AnyFun, Fun, FunN, and after introducing this change I would have to deal with AnyFun, Fun< Number >, Fun< bool >, FunN< Number >, FunN< bool >. And even then I would want it to match AnyFun against any function that isnt matched themselves. Like this:
engine.Eval(src).Match()
.Case((Fun<Number> result) => Console.WriteLine("I am special!!!"))
.Case((AnyFun result) => Console.WriteLine("I am a generic function"))
.Do();
Does anyone have any suggestions for a better implementation, that handles adding new types better? Or are there any other suggestions for how to get the result in a type safe manner? Also, should I have a common base class for all the return types (and add a new type for bool)?
Performance is not an issue, btw.
Take care,
Kerr
EDIT:
After reading the feedback, I have created this matcher class instead.
public class Matcher
{
private Action _onCase;
private Result _result;
public Matcher(Result r)
{
_onCase = null;
_result = r;
}
public Matcher Case<T>(Callback<T> fn)
{
if (_result.Val is T && _onCase == null)
{
_onCase = () => fn((T)_result.Val);
}
return this;
}
public void Else(Callback<object> fn)
{
if (_onCase != null)
_onCase();
else
fn(_result.Val);
}
public void Do()
{
if (_onCase == null)
throw new Exception("Must add a new exception for this... but there was no case for this :P");
_onCase();
}
}
Its shorter, but the order of the cases matter. For example, in this case the Fun option will never run.
.Case((AnyFun result) => Console.WriteLine("AAANNNNNNNYYYYYYYYYYYYY!!!!"))
.Case((Fun result) => Console.WriteLine("I am alone"))
But it will if you switch places.
.Case((Fun result) => Console.WriteLine("I am alone"))
.Case((AnyFun result) => Console.WriteLine("AAANNNNNNNYYYYYYYYYYYYY!!!!"))
Is it possible to improve that? Are there any other issues with my code?
EDIT 2:
Solved it :D.
Your matcher could handle unlimited types by doing something like this:
public class Matcher
{
private readonly Result result; // pass this in
private readonly List<Func<Result, bool>> cases = new ...();
public Matcher Case<T>(Action<T> action)
{
cases.add(result =>
{
if(typeof(T).IsAssignableFrom(result.Value.GetType()))
{
action((T)(result.Value));
return true;
}
return false;
}
return this;
}
public void Do()
{
for each(var #case in cases)
{
if(#case(result)) return;
}
}
}
I think you don't actually need a list, unless your Result doesn't have a Value until later on. I don't quite understand your object model, but if the type of the result is known, then don't use a list and just do the type test immediately.
If you always want to treat a DSL result in the same way
If you always want to treat a result in the same way (such as if you always want to convert/adapt a specific type of DSL object in the same manner), I suggest using one or more dictionaries where you put adapter delegates like this.
I don't know exactly how you plan to extend your application, but it seems to me like it's a good idea in your case to have one separate dictionary per return type, and let them all have zero or one input parameters. (Instead of using several parameters, just wrap the DSL parameters that you want to return into one single object).
An example:
public class SomeClass
{
public IDictionary<Type, Action<object>> RegistryVoid { get; set; }
public IDictionary<Type, Func<object, int>> RegistryInt { get; set; }
public void SomeDlsMethod()
{
...
// Example when you need to convert your DSL data object to int:
int value = RegistryInt[someDslObject.GetType()](someDslObject);
}
}
If you want to treat a DSL result differently
If you want to treat a DSL result differently in your code, I suggest using the TypeSwith found here. TypeSwitch is simply a simpler way than using multiple if/else-statements and casting. With this approach you can specify the logic where you use it, so you are not limited to the logic you put into the dictionaries. (TypeSwitch can easily be modified to become an extension method if you prefer that).
Example:
public class SomeClass
{
public void SomeDlsMethod()
{
TypeSwitch.Do(someDslObject,
TypeSwitch.Case<DslObjectA>(someDslObjectA => ...),
TypeSwitch.Case<DslObjectB>(someDslObjectB => ...),
TypeSwitch.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>();
}
}
}

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"));

Categories