This is a bit of a weird one.
I'm building a web application and I was putting together a simple factory-pattern-like thing to handle some object instantiation. I don't like big ugly switch-case blocks, so I tend to do this:
public enum Option
{
Option1,
Option2,
Option3
}
public Dictionary<Option, Func<MyBaseClass>> OptionMapping
= new Dictionary<Option, Func<MyBaseClass>>
{
{ Option1, () => new DerivedClassOne() },
{ Option2, () => new DerivedClassTwo() },
{ Option3, () => new DerivedClassThree() }
};
and then the switch block becomes MyBaseClass selectedThing = OptionMapping[currentOption]();
.
It occurred to me while writing this code that if you ever had a situation where two options required the same action, you'd end up with the same Func<>
in two places, which I'd rather avoid. Assuming for the moment that you can't just refactor some logic to merge those two options into one, I'd like to know if there's a way to get one Func
to call the other.
My first thought was this:
public Dictionary<Option, Func<MyBaseClass>> OptionMapping
= new Dictionary<Option, Func<MyBaseClass>>
{
{ Option1, () => new DerivedClassOne() },
{ Option2, () => new DerivedClassTwo() },
{ Option3, () => this[Option1]() }
};
but a quick test in LINQPad tells me that doesn't work because of course the this
refers to the class in which the code is written, not the Dictionary
(apparently I've spent too much time in languages where this
is more fickle). My second thought was to change it to () => OptionMapping [Option1]()
, but that gives an error that you're trying to use OptionMapping
before it's initialised. You could of course do this:
public Dictionary<Option, Func<MyBaseClass>> OptionMapping
= new Dictionary<Option, Func<MyBaseClass>>
{
{ Option1, () => new DerivedClassOne() },
{ Option2, () => new DerivedClassTwo() }
};
OptionMapping.Add(Option3, () => OptionMapping [Option1]());
which works, but isn't as pretty. So, this question is mostly one of curiosity.
Is there a way to access one element of a Dictionary
from another? More generally, does C# have a keyword like this
that means "the object I'm inside right now at time of execution", rather than "the containing object at write time"?
EDIT:
Originally, the Dictionary
was static, so the error I mentioned about using it before it's been initialised wouldn't happen. The static
was actually a leftover from pasting in a larger block of code and editing it down, and then copy-pasting the error around.
So, the main answer being posted is about having a separate object to store the Func
and then adding that to the Dictionary
twice. That makes sense, and is more or less what I went with in the end (for various reasons it also made some of the surrounding code a bit cleaner) but it's kind of avoiding the part of the question I'm most interested in, which is whether it's possible in C# to access the object you're in at runtime, so that an object could access the dictionary (or list, or array, etc) that they're currently within.
To return a dictionary, first create the dict object within the function body, assign it to a variable your_dict , and return it to the caller of the function using the keyword operation “ return your_dict “.
dict() versus {} Python provides two different ways to initialize dictionaries - probably the most used type in Python codes. If you are interested in performance, you will find a lot of posts where it clearly states that dict() is slower than simply using {}.
This should work:
private static Dictionary<Option, Func<MyBaseClass>> OptionMapping
= new Dictionary<Option, Func<MyBaseClass>> {
{ Option.Option1, () => new DerivedClassOne() },
{ Option.Option2, () => new DerivedClassTwo() },
{ Option.Option3, () => OptionMapping[Option.Option2]() }
};
Demo on ideone.
The problem with this approach is that Option3
contains a different Func
object, which relies on another Func
to produce its output every time you call it.
I think this is not as nice as a solution in which you make a shared Func
object explicitly, and place it in the dictionary several times (i.e. your second code snippet, or the alternative below)
private static Dictionary<Option, Func<MyBaseClass>> OptionMapping;
static MyClass() {
Func<MyBaseClass> makeDerivedTwo = () => new DerivedClassTwo();
OptionMapping = new Dictionary<Option, Func<MyBaseClass>> {
{ Option.Option1, () => new DerivedClassOne() },
{ Option.Option2, makeDerivedTwo },
{ Option.Option3, makeDerivedTwo }
};
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With