Emulating F# `with` keyword in C# - 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();
}
}

Related

How to correctly implement this IComparable?

I have problems wit hthe implementation of a generic sorting algorithm.
We need to implement quicksort and selection sort, and a class which should be sortable using these functions. The functions should be generic, and thus work on other classes as well.
I tested the quicksort. It works perfectly on a List. However, when trying to execute it on my own comparable class, it says:
There is no implicit reference conversion from 'SNIP' to 'System.IComparable'
Do you guys have any idea what the problem can be?
Here is my comparable class:
public class SNIP : IComparable
{
private long lCost { get; set; }
public SNIP(long lCost)
{
this.lCost = lCost;
}
public int CompareTo(object obj)
{
if (obj == null) return 1;
SNIP oOtherPlank = obj as SNIP;
if (oOtherPlank != null)
return this.lCost.CompareTo(oOtherPlank.lCost);
else
throw new ArgumentException("Can only compare SNIPs.");
}
}
Thanks in advance!
Thanks to #Sweeper, the comparable is now fixed.
Like he said, I had to define my class better:
public class SNIP : IComparable<SNIP>
{
private long lCost { get; set; }
public SNIP(long lCost)
{
this.lCost = lCost;
}
public int CompareTo(SNIP obj)
{
if (obj == null) return 1;
SNIP oOtherSnip= obj as SNIP;
if (oOtherSnip!= null)
return this.lCost.CompareTo(oOtherSnip.lCost);
else
throw new ArgumentException("Can only compare SNIPs.");
}
}
It is also important to note that this only works when the argument of the CompareTo method is actually of the right class. I tried defining the class as IComparable before, but it didn't work because the argument in CompareTo was set to an object. By changing both the CompareTo header and the class header, the problem is fixed and the sorting now works.
Thanks a lot :-)
You can implement generic IComparable<SNIP>, not IComparable which is very simple: this is always geater than null and if we compare with not null other we should check lCost.
public class SNIP : IComparable<SNIP>
{
private long lCost { get; set; }
public SNIP(long lCost)
{
this.lCost = lCost;
}
public int CompareTo(SNIP other) => other is null
? 1
: lCost.CompareTo(other.lCost);
}
then you can sort: note that since List<SNIP> is generic, the generic IComparable<SNIP> will be used on sorting.
List<SNIP> list = new List<SNIP>()
{
new SNIP(5),
new SNIP(1),
new SNIP(3),
};
list.Sort();

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

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

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

How can you return a Collection<ConcreteType> as a Collection<Interface>?

I have a concrete class that contains a collection of another concrete class. I would like to expose both classes via interfaces, but I am having trouble figuring out how I can expose the Collection<ConcreteType> member as a Collection<Interface> member.
I am currently using .NET 2.0
The code below results in a compiler error:
Cannot implicitly convert type
'System.Collections.ObjectModel.Collection<Nail>' to
'System.Collections.ObjectModel.Collection<INail>'
The commented attempt to cast give this compiler error:
Cannot convert type
'System.Collections.ObjectModel.Collection<Nail>' to
'System.Collections.ObjectModel.Collection<INail>' via a
reference conversion, boxing conversion, unboxing conversion, wrapping
conversion, or null type conversion.
Is there any way to expose the collection of concrete types as a collection of interfaces or do I need to create a new collection in the getter method of the interface?
using System.Collections.ObjectModel;
public interface IBucket
{
Collection<INail> Nails
{
get;
}
}
public interface INail
{
}
internal sealed class Nail : INail
{
}
internal sealed class Bucket : IBucket
{
private Collection<Nail> nails;
Collection<INail> IBucket.Nails
{
get
{
//return (nails as Collection<INail>);
return nails;
}
}
public Bucket()
{
this.nails = new Collection<Nail>();
}
}
C# 3.0 generics are invariant. You can't do that without creating a new object. C# 4.0 introduces safe covariance/contravariance which won't change anything about read/write collections (your case) anyway.
Just define nails as
Collection<INail>
Why not just return it as an interface, just have all your public methods in the interface, that way you don't have this problem, and, if you later decide to return another type of Nail class then it would work fine.
What version of .Net are you using?
If you are using .net 3.0+, you can only achieve this by using System.Linq.
Check out this question, which solved it for me.
There is one solution that might not be quite what you are asking for but could be an acceptable alternative -- use arrays instead.
internal sealed class Bucket : IBucket
{
private Nail[] nails;
INail[] IBucket.Nails
{
get { return this.nails; }
}
public Bucket()
{
this.nails = new Nail[100];
}
}
(If you end up doing something like this, keep in mind this Framework Design Guidelines note: generally arrays shouldn't be exposed as properties, since they are typically copied before being returned to the caller and copying is an expensive operation to do inside an innocent property get.)
use this as the body of your property getter:
List<INail> tempNails = new List<INail>();
foreach (Nail nail in nails)
{
tempNails.Add(nail);
}
ReadOnlyCollection<INail> readOnlyTempNails = new ReadOnlyCollection<INail>(tempNails);
return readOnlyTempNails;
That is a tad bit of a hacky solution but it does what you want.
Edited to return a ReadOnlyCollection. Make sure to update your types in IBucket and Bucket.
You can add some generics. Fits better, more strongly coupled.
public interface IBucket<T> where T : INail
{
Collection<T> Nails
{
get;
}
}
public interface INail
{
}
internal sealed class Nail : INail
{
}
internal sealed class Bucket : IBucket<Nail>
{
private Collection<Nail> nails;
Collection<Nail> IBucket<Nail>.Nails
{
get
{
return nails; //works
}
}
public Bucket()
{
this.nails = new Collection<Nail>();
}
}
This way the Collection<Nail> you return from Bucket class can only ever hold Nails. Any other INail wont go into it. This may or may not be better depending on what you want.
Only if you want Collection<INail> (the interface property) you return from Bucket to hold other INails (than Nails) then you may try the below approach. But there is a problem. On one side you say you want to use a private Collection<Nail> in Bucket class and not a Collection<INail> because you dont want to accidentally add other INails from Bucket class into it but on the other side you will have to add other INails from outside of Bucket class. This is not possible on the same instance. Compiler stops you from accidentally adding any INail to a Collection<Nail>. One way is to return a different instance of Collection<INail> from your Bucket class from the existing Collection<Nail>. This is less efficient, but could be the semantics you are after. Note that this is conceptually different from above
internal sealed class Bucket : IBucket
{
private Collection<Nail> nails;
Collection<INail> IBucket<Nail>.Nails
{
get
{
List<INail> temp = new List<INail>();
foreach (Nail nail in nails)
temp.Add(nail);
return new Collection<INail>(temp);
}
}
public Bucket()
{
this.nails = new Collection<Nail>();
}
}
C# doesn't support generic collections covariance (it's only supported for arrays).
I use an adapter class in such cases. It just redirects all calls to the actual collection, converting values to the required type (doesn't require copying all list values to the new collection).
Usage looks like this:
Collection<INail> IBucket.Nails
{
get
{
return new ListAdapter<Nail, INail>(nails);
}
}
// my implementation (it's incomplete)
public class ListAdapter<T_Src, T_Dst> : IList<T_Dst>
{
public ListAdapter(IList<T_Src> val)
{
_vals = val;
}
IList<T_Src> _vals;
protected static T_Src ConvertToSrc(T_Dst val)
{
return (T_Src)((object)val);
}
protected static T_Dst ConvertToDst(T_Src val)
{
return (T_Dst)((object)val);
}
public void Add(T_Dst item)
{
T_Src val = ConvertToSrc(item);
_vals.Add(val);
}
public void Clear()
{
_vals.Clear();
}
public bool Contains(T_Dst item)
{
return _vals.Contains(ConvertToSrc(item));
}
public void CopyTo(T_Dst[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public int Count
{
get { return _vals.Count; }
}
public bool IsReadOnly
{
get { return _vals.IsReadOnly; }
}
public bool Remove(T_Dst item)
{
return _vals.Remove(ConvertToSrc(item));
}
public IEnumerator<T_Dst> GetEnumerator()
{
foreach (T_Src cur in _vals)
yield return ConvertToDst(cur);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public override string ToString()
{
return string.Format("Count = {0}", _vals.Count);
}
public int IndexOf(T_Dst item)
{
return _vals.IndexOf(ConvertToSrc(item));
}
public void Insert(int index, T_Dst item)
{
throw new NotImplementedException();
}
public void RemoveAt(int index)
{
throw new NotImplementedException();
}
public T_Dst this[int index]
{
get { return ConvertToDst(_vals[index]); }
set { _vals[index] = ConvertToSrc(value); }
}
}
you could use the Cast extension
nails.Cast<INail>()
I can't test it here to provide a more comprehensive example, as we are using .NET 2.0 at work (gripe gripe), but I did have a similar question here

Categories