In Foof We Trust: A Dialogue
User: The typeof(T) operator in C# essentially means “compiler, generate some code that gives me an object at runtime which represents the type you associate with the name T”. It would be nice to have similar operators that could take names of, say, methods and give you other metadata objects, like method infos, property infos, and so on. This would be a more pleasant syntax than passing ugly strings and types and binding flags to various Reflection APIs to get that information.
Eric: I agree, that would be a lovely sugar. This idea has been coming up during the C# design meeting for almost a decade now. We call the proposed operator “infoof”, since it would return arbitrary metadata info. We whimsically insist that it be pronounced “in-foof”, not “info-of”.
User: So implement it already, if you’ve been getting requests for the better part of ten years! What are you waiting for?
Eric: First, as I’ve discussed before on my blog, we have a very limited time and money budget for design, implementation, testing, documentation and maintenance, so we want to make sure we’re spending it on the highest-value features. This one has never made it over that bar.
Second, the feature seems at first glance to be simple, but in fact has a rather large “design surface” and would require adding a fair amount of new syntax to the language.
Third, it is nothing that you cannot do already with existing code; it’s not necessary, it’s just nice.
All these are enough “points against” the feature that it’s never made it into positive territory. It will stay on the list for hypothetical future versions of the language, but I would not expect it to ever happen.
User: Can you elaborate on some of the problems?
Eric: Let’s start with a simple one. Suppose you have infoof(Bar) where Bar is an overloaded method. Suppose there is a specific Bar that you want to get info for. This is an overload resolution problem. How do you tell the overload resolution algorithm which one to pick? The existing overload resolution algorithm requires either argument expressions or, at the very least, argument types.
Expressions seem problematic. Either they are evaluated unnecessarily, perhaps producing unwanted side effects, or you have a bunch of expressions in code that looks like a function call but isn’t actually. Either way is potentially confusing. So we’d want to stick with types.
User: Well then, it ought to be straightforward then. infoof(Bar(int, int)), done.
Eric: I notice that you’ve just introduced new syntax; nowhere in C# previously did we have a parenthesized, comma-separated list of types. But that’s not at all hard to parse.
User: Exactly. So go with that.
Eric: OK smart guy, what about this strangely familiar case?
class C<T>
{
public void Bar(int x, T y) {}
public void Bar(T x, int y) {}
public void Bar(int x, int y) {}
}
class D : C<int>
{ …
You have some code in D that says infoof(Bar(int, int)). There are three candidates. Which do you pick?
User: Well, which would overload resolution pick if you called Bar(10, 10) ? Overload resolution tiebreaker rules say to pick the non-generic version when faced with this awful situation.
Eric: Great. Except that’s not the one I wanted. I wanted the method info of the second version. If your proposed syntax picks one of them then you need to give me a syntax to pick the others.
User: Hmm. It's hard because overload resolution actually gives you no way to force the call to go to one of the two “generic param” methods in this bizarre case, so some mechanism stronger than overload resolution needs to be invented if you want the feature to allow getting info of any method.
But this is a deliberately contrived corner case; just cut it. You don’t have to support this scenario.
Eric: And now you start to see how this always goes in the design meeting! It is very easy to design a feature that hits what initially looks like 80% of the cases. And then you discover that the other 80% of the cases are not covered, and the feature either takes 160% of its budget, or you end up with a confusing, inconsistent and weak feature, or, worse, both.
And how do we know what scenarios to cut? We have to design a feature that does something in every possible case, even if that something is an error. So we have to at least spend the time to consider every possible case during the design. There are a lot of weird cases to consider!
User: What are some of the other weird cases?
Eric: Just off the top of my head, here are a few. (1) How do you unambiguously specify that you want a method info of an specific explicit interface implementation? (2) What if overload resolution would have skipped a particular method because it is not accessible? It is legal to get method infos of methods that are not accessible; metadata is always public even if it describes private details. Should we make it impossible to get private metadata, making the feature weak, or should we make it possible, and make infoof use a subtly different overload resolution algorithm than the rest of C#? (3) How do you specify that you want the info of, say, an indexer setter, or a property getter, or an event handler adder?
There are lots more goofy edge cases.
User: I’m sure that we could come up with a syntax for all of those cases.
Eric: Sure. None of these problems are unsolvable. But they almost all require careful design and new syntax, and we would soon end up spending most of our design, implementation and testing budget on this trivial “sugar” feature, budget that we could be spending on more valuable features that solve real problems.
User: Well, how about you do the easy 80% and make “the other 80%” into error cases? Sure, the smaller feature is weaker and might be inconsistent, but something is better than nothing, and it’ll be cheaper to just do the easy ones.
Eric: That doesn’t actually make it cheaper a lot of the time. Any time we make a corner case into an error we need to carefully specify exactly what the error case is so that we can implement it correctly and test it confidently. Every error case still spends design, implementation and test budget that could have been spent elsewhere.
We would need to come up with a sensible error message, localize the error message into I don’t know how many languages, implement the code that detects the weird scenarios and gives the right error, test the error cases and document them. And we would need to deal with all the users who push back on each error case and request that it work for their specific scenario.
Trying to scope the feature down so that it is smaller adds work, and it is possible that it adds more work in the long run than simply making the larger version of the feature work in the first place. There are no cheap features.
User: Bummer. Because most of the time I really just want to get the method info of the method I’m currently running, for logging purposes during my test suites. It seems a shame to have to solve all these overload resolution problems just to get information about what’s happening at runtime.
Eric: Maybe you should have said that in the first place! The aptly named GetCurrentMethod method does that.
User: So what you’re telling me is no infoof?
Eric: It’s an awesome feature that pretty much everyone involved in the design process wishes we could do, but there are good practical reasons why we choose not to. If there comes a day when designing it and implementing it is the best way we could spend our limited budget, we’ll do it. Until then, use Reflection.
Comments
Anonymous
May 21, 2009
The comment has been removedAnonymous
May 21, 2009
The comment has been removedAnonymous
May 21, 2009
Given that the type of infoof(Thing) can already vary between PropertyInfo and MethodInfo, you could also allow it to be IEnumerable<MethodInfo> if the method name is overloaded.Anonymous
May 21, 2009
The comment has been removedAnonymous
May 21, 2009
> Given that the type of infoof(Thing) can already vary between PropertyInfo and MethodInfo, you could also allow it to be IEnumerable<MethodInfo> if the method name is overloaded. When you use infoof(), you'd normally want to get one particular method. If you instead get a sequence, and still has to work with reflection methods on those MethodInfo objects to find the method you need (by argument count etc), you might as well just use reflection from the get go. For infoof() to be usable for scenarios where it's desirable, it really needs to be able to unambiguously identify the specific method/property.Anonymous
May 21, 2009
The perfect is the enemy of the good. Point taken. But my point is that the resource-consuming mediocrity is the enemy of the awesome. Like I said before, how many free unicorns are you willing to give up in order to get this free pony? -- EricAnonymous
May 21, 2009
@pminaev - yes, but the remaining problems could then be solved with some extension methods defined on IEnumerable<MethodInfo>. MethodInfo mi = infoof(SomeMethod).GetOverload<int, string>(); The overload selection would not be checked at compile time, but at least the name would be.Anonymous
May 21, 2009
I agree with pminaev. In many ways, I love WPF, but the whole string names for dependency properties and OnPropertyChange is an ugly mess. I imagine that all of the reflection that WPF is doing is probably also a performance bottleneck (although I can't back that up). Perhaps the real solution to this problem isn't infoof but something like a property delegate.Anonymous
May 21, 2009
The comment has been removedAnonymous
May 21, 2009
I no longer pine for infoof now that we have expression trees, but it does seem a little unfortunate that there are now many .NET projects out there with relatively similar chunks of code that inspect the expression tree and give you back the appropriate info instance. What would be nice is if the BCL team would add a small library to do this work. That way when you get people still complaining about the lack of infoof, you can point them to the library and be done with it.Anonymous
May 21, 2009
"Like I said before, how many free unicorns are you willing to give up in order to get this free pony?" I would have given up pretty much everything in .Net 4 for this. But that's just me - I don't use dynamic and all that, and I can't stand string properties. I agree with pminaev - this should be an extremely verbose feature, but it should exist. His syntax is pretty much what I thought of. You treat this feature as syntactic sugar, but there is no way to do this currently except string properties - which are the root of all evil because they are not compile-time checked. </rant> Off topic: Eric, what about that memoization post you promised two and a half months ago?Anonymous
May 21, 2009
The comment has been removedAnonymous
May 21, 2009
The comment has been removedAnonymous
May 21, 2009
The comment has been removedAnonymous
May 21, 2009
Observation: I think the real reason people want an infoof operator is that they don't want to use reflection, even though what they're asking for is available via reflection. That seems to stem from reflection being, well, confusing to use, and a little unwieldy. But like everyone else I write some unit tests, muddle through it, and when it works I have a gin and try to forget. Given that, what is the real-world context most people want this stuff for? Enlighten me. If anyone's listening, I'd like a data access technology from MS that isn't end-of-lifed after version 1.Anonymous
May 21, 2009
The comment has been removedAnonymous
May 21, 2009
Just before c# 3 was released I read an article about reflection and Lambda and combining the two to make type safe reflection: http://www.clariusconsulting.net/blogs/kzu/archive/2006/07/06/TypedReflection.aspx it might be intereseting to some of the followers of this post.Anonymous
May 21, 2009
GetCurrentMethod is not a good solution. Method can be inlined and GetCurrentMethod will return the method that IL was inlined into. What's inlined can be changed between versions of call and so the only thing one can do is to add NoInlining attribute. It's uglyAnonymous
May 21, 2009
> Method can be inlined and GetCurrentMethod will return the method that IL was inlined into. I'm not 100% certain on this, but I believe that calling GetCurrentMethod() will actually prevent the calling method from being inlined, specifically so that you don't get wrong results. GetCallingAssembly() is the one that can give you the wrong result because of inlining (and documented as such).Anonymous
May 21, 2009
"Like I said before, how many free unicorns are you willing to give up in order to get this free pony? -- Eric" Haha, nice one Eric. That made me laugh. You have quite a way with words ;) (That is so going on my quote list) As always I really appreciate the insight into the decision making process behind adding features. Very nice article :)Anonymous
May 21, 2009
The comment has been removedAnonymous
May 21, 2009
Hi Eric, I'm enjoying the back-story behind diferent feature decisions. I enjoyed the User / Eric conversation :) KirkAnonymous
May 22, 2009
Not sure how I feel specifically about infoof()..... But 100% certain that I despise ANYTHING that requires me to use a string to represent information. The lack of compile time validation has probably caused more bugs (at least in "successful" builds, not necessarily in releases) than any other single factor since I have been programming in C#. Because of this, our mandate for testing (which has to be manuaklly written) when using any feature that is string based, costs significant $$$ [we estimate $10-$25 per usage!!] If anything can be done to provide alternatives which do not rely on strings, it would trump almost every other item on "my" backlog (including most of the 3.5 and 4.0 features]Anonymous
May 22, 2009
Like Paul Batum said, why doesn't the team set up an "infoof" project on codeplex, promote it and open it up to everyone to cover the accepted 80 % classes with the current syntax? this could help the team in also seeing where they'd need to focus their attention when this is discussed again...Anonymous
May 22, 2009
The comment has been removedAnonymous
May 22, 2009
I can attest to the trickiness of this problem. I have been developing a library to help me generate type safe MSIL with Reflection.Emit, which define classes to wrap the various FooBuilder and FooInfo classes, and encapsulate calls to ILGenerator.Emit with the correct OpCode and validating that the types are consistent. And I have built an associated tool, that produces a library of static readonly properties to represent the members of a given class as objects from my library. Currently, the support for generics and private/protected members in this tool leaves much to be desired, and I find it is a hard problem to even define what the correct behavior is, even when the use case is only my personal use.Anonymous
May 22, 2009
I previously mentioned some hypothetical C# fieldof and methodof operators, which would obtain FieldInfo and MethodInfo objects, in the same way that typeof retrieves Type at runtime. Eric Lippert explains the pros and cons of a combined infoof operator,Anonymous
May 22, 2009
The comment has been removedAnonymous
May 22, 2009
I think it is quite "natural" that the design process for a feature supposed to give information about some existing language feature X reveals lots of corner cases if X itself has corner cases (like the "odious overloads" examples). In other words, the "infoof" design problems reveal design problems inside the space "of" refers to.Anonymous
May 22, 2009
I think, it's wrong to propose reflection as an alternative to "nameof" (or whatever you call it) and the example at the end of the story to be honest is not realistic. Not realistic? Upon what data do you base that conclusion? Do you, like me, also get to see thousands of emails from C# users describing what features they'd like to see, and their real-world scenarios that drive those feature requests? Do you get input from focus groups? Do you get together with a few hundred MVPs once a year and talk to them about possible new features and how they'd use them? If you don't do these things then how do you know what is "realistic" for the industry as a whole? -- Eric Why do I need "nameof" operator? Mostly just for two things. First, to retrieve the name of the variables for assertions (how many ArgumentExceptions you throw in your code? how often you refactor your code?). Next, for attributes. Current framework architecture requires to write method or property name as a string when it is needed to reference it in attribute. I'd like to see more checks in this area at complie-time due to possible refactorings, typos, etc. So, as for me something like [ItemsSource(nameof(MyClass, Items))] class MyCLass { public IList Items {get; } } would be quite ok. Will it be possible to use infoof in cases like this? Can it be used within existing framework infrastructure that requires compile time string input? I'm a little afraid that while trying to solve all the possible issues the feature will not be usable in the end. The attribute case is one of the most common driving scenarios for this feature request. -- Eric If there was quite stupid "nameof" operator that just generated the compile time string from resolved item name or error in case of any ambiguities it would be much much more better than now when we deal with such errors in runtime. Indeed, it is always easier to make a weak feature that doesn't do anything difficult. The down side is that weak features still cost a lot, and you end up with a language full of weak features. -- EricAnonymous
May 22, 2009
I'd far rather have more metaprogramming-like features such as expression trees than an improvement on reflection. I don't see why people would want infoof over named and optional parameters and especially co- and contravariance. I have want for those features almost in every project, while I only felt the need to use reflection once or twice.Anonymous
May 23, 2009
Thank you Eric for your explanations, now I can sleep well :) When I was talking about "not realistic" example I just meant that this feature is something different, e.g. there are several logging frameworks that write down caller name (via reflection, I don't think infoof will help such frameworks) and it takes a few minutes to google the solution. Of course it's definitely better to specify attributes with say MethodInfo instead of method names but I was just wondering if infoof returns MethodInfo how can it be converted to string at compile time to coexist with the way things are done now (this is actually a week feature, it's already there and we have to live with it). I believe you have the answer but from my point of view it's a real challenge to combine these two worlds and I can only hope you found a way to do it.Anonymous
May 23, 2009
Two observations: "It is very easy to design a feature that hits what initially looks like 80% of the cases. And then you discover that the other 80% of the cases are not covered, " How can both be 80%? Am I missing something here? It should be '80% of the cases, and then you discover that the other 20% of the cases are not covered'. It's a joke. You get through what you THINK are 80% of the cases, you've spent 80% of your budget on them, and then you discover that in fact you are only half done. In that scenario you are going to either ship a half-done feature, or you're going to spend 160% of your budget. Hence the joke. -- Eric Secondly, are you sure your example class C<T>
{
public void Bar(int x, T y) {}
public void Bar(T x, int y) {}
public void Bar(int x, int y) {}
}
class D : C<int>
{ … is correct given this: http://blogs.msdn.com/samng/archive/2008/02/13/generic-method-substitutions-and-unification.aspx and http://blogs.msdn.com/samng/archive/2008/03/04/generic-method-substitutions-and-unification-part-two.aspx ? Indeed, as Sam's blog notes, this is a case where what is allowed by the C# language and what is allowed by the CLR are different. We're still trying to figure out what the right resolution is; until we do, I strongly recommend that you avoid situations like this. -- EricAnonymous
May 23, 2009
The comment has been removedAnonymous
May 24, 2009
Fair enough, up to a point. What I've wished for many a time (and I don't think I'm alone) is a nameof operator I can use with method arguments so as to populate the ArgumentException's parameter in such a way that it is type-safe + refactor-safe. Getting full ParameterInfo metadata would be a bonus of course, but not required to be useful. I struggle to think when nameof(argument) (or infoof(argument) for that matter) could ever have an edgecase associated with it, but I agree this would be (in your terms ) a 'week' feature in that it would only work within the scope of the method that has the arguments. [in the rest of the world we call this incremental delivery: solve the easy problems first, and come back to the hard ones if you have time] Note that a more general 'nameof' operator skips your overload resolution problem, since it doesn't do any : you still need to pass the output from nameof to a reflection API along with bindingflags, args etc... to resolve to a method. It just saves you from littering your codebase with strings that you already put in the codebase once (as method/property/argument identifiers) and struggle to see why you should have to duplicate.Anonymous
May 25, 2009
The comment has been removedAnonymous
May 25, 2009
> private members: just be consistent with typeof and disallow access typeof() does not disallow access to private types, if the code that uses it has access to them.Anonymous
May 25, 2009
@pminaev Eric wrote "(2) What if overload resolution would have skipped a particular method because it is not accessible? It is legal to get method infos of methods that are not accessible; metadata is always public even if it describes private details. Should we make it impossible to get private metadata, making the feature weak, or should we make it possible, and make infoof use a subtly different overload resolution algorithm than the rest of C#?" I think in the context of the question the comment makes sense. BTW, making infoof able to access members that would otherwise be unaccessible would be a dangerous feature anyway. there should not be any hard-coded references to private members of other assemblies in any case, and doing it via reflection wouldn't make it any better. stuff is private for a reason. we should only access private members via reflection if they are dynamically discovered, as in a serializer. but the whole discussion is moot anyway. we're not going to get it.Anonymous
May 26, 2009
If you don't read Eric Lippert's Fabulous Adventures In Coding , you're really missing out on some greatAnonymous
May 26, 2009
If you don't read Eric Lippert's Fabulous Adventures In Coding , you're really missing outAnonymous
May 29, 2009
Indeed there's a balance between usefulness and cost. Uniquely identifying a method is horribly complicated, probably requires a clumsy syntax, and surely adds a lot of complexity (= costs). At the same time I don't see many use cases for statically getting a MethodInfo. Everything I can think of is ouputting the method name in messages (e.g. logging, or assertations). For those scenarios GetCurrentMethod or a static aspect weaver like Post# can do wonders. And even if they break that's not my code logic that's breaking, just some outdated messages. I think this pretty much rules out a methodof operator, and I am fine with this. But please give the propertyof a chance. You wrote that doing only part of the feature is "weak", but is it really? In that case typeof is "weak" but I'm sure you don't want to remove it, do you?
- propertyof is not so expensive. Properties are relatively easy to identify: propertyof(Length), or maybe propertyof(Array.Length) when outside the class. The only slightly tricky case is indexed properties, which are unsupported in C# anyway. So the worse case left is generic types... propertyof(List<T>.Count).
- Ideally the compiler could infer from usage if propertyof should return a string (the property name) or a PropertyInfo instance.
- This would be incredibly useful! Use cases are many. We currently must write property names as string at tons of places in the framework: attributes (e.g. ItemsSourceAttribute), INotifyPropertyChanged (very common those days), DependencyProperties registration, ... And you know what the problem with strings is. Say hello to runtime errors because of typos, and goodbye to safe refactoring, "Find all references", etc. I personnally don't think your argument to justify not implementing propertyof holds... regarding infoof in its genericity, sure. But in the particular propertof case, no.
Anonymous
June 03, 2009
Пользователь: Оператор typeof(T) в C#, по существу, означает «компилятор, сгенерируй некий код, которыйAnonymous
June 24, 2009
I agree completely with both Eric and James Hart. How about we compromise, and get a way to generate a ldtoken instruction for the current method only? Even better would be one that returns a RuntimeMethodHandle instead of a MethodBase, since I think the usual case is to pass it to some sort of diagnostic method that may only need to use it in rare cases where something is wrong and so in the normal case it may be able to skip the cost of constructing a MethodBase from a RuntimeMethodHandle (metadata loading, etc); but I can understand why, for consistency with the existing typeof keyword, which both ldtoken's the RuntimeTypeHandle and creates a Type for it, it might be desirable just to have it always make the MethodBase.Anonymous
July 09, 2009
What you think about "operator .?" ? <object>.?<member> "operator .?" is equivalent of construction
NullMemberType result; if (<object> != null) result = <object>.<member>; else result = null;
where MemberType is type of <member> result where NullMemberType is MemberType for case MemberType is class; MemberType for case MemberType is Nullable<T>; Nullable<MemberType> for case MemberType is struct void for case MemberType is void i.e. for MemberType is void - this operator is equivalent of construction
if (<object> != null) <object>.<member>();
this operator is very needed in script and business logic, and this operator is realized Null Object Pattern (http://en.wikipedia.org/wiki/Null_Object_pattern) example of using now
int? age = null; var root = Root; if (root != null) { var config = root.Config; if (config != null) { var user = config.User; if (user != null) age = user.Age; } } if (age != null && age.Value >= 21) { //bla-bla }
whit "operator .?"
if (Root.?Config.?User.?Age >= 21) {//bla-bla}
now this operator realized is very ugly as if (Root.no( => _.Config).no( => _.User).nv( => _.Age) >= 21) {//bla-bla} public static class NullableExtensions { public static void _n<TItem>(this TItem item, Action<TItem> func) { if (item != null) func(item); } public static TResult _no<TItem, TResult>(this TItem item, Func<TItem, TResult> func) where TResult : class { if (item == null) return null; return func(item); } public static TResult? _nv<TItem, TResult>(this TItem item, Func<TItem, TResult?> func) where TResult : struct { if (item == null) return null; return func(item); } public static TResult? _nv<TItem, TResult>(this TItem item, Func<TItem, TResult> func) where TResult : struct { if (item == null) return null; return func(item); } } ps what is better? "operator.?" or "operator?."
Anonymous
September 09, 2009
I'm confused. I was looking at some Reflector C# output for code generated by PostSharp, and it uses a "methodof" operator I'd never heard about before. Here's an example of the code it has generated: ~targetMethod~1 = methodof(SomeClass.SomeMethod); Is this just fictional C# syntax that Reflector has whirled up by examining what the IL is doing? The IL is: L_003a: ldtoken instance class [SomeAssembly]ReturnType SomeType::SomeMethod(class [SomeAssembly]SomeArgumentType, string) L_003f: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle) Anyone point me to some links to learn from? This isn't my area of expertise...Anonymous
March 03, 2010
Does your argument about "weak features" and having to document the error cases, not seem to apply neatly to the case of generic custom attributes? It is my understanding that the CLR understands custom attributes of generic types; only the C# compiler doesn't. It seems to me that generic custom attributes should have been implemented according to your argumentation, because you claim the amount of effort in implementing, documenting and maintaing the error case is comparable to that of implementing, documenting and maintaing the working feature. How many people regularly request this feature, and what are the difficulties and downsides of implementing it? Also, I notice one user has commented that they would like to be able to use infoof() in custom attributes. Since typeof() is allowed, this makes sense - it is in some sense a constant expression. But then why not simply allow expression trees and/or lambda expressions in custom attributes? They, too, are somewhat of a constant (in the sense that the compiler need not run any user code to evaluate it). Isn't this another case of a similar nature as the above, where the amount of effort of supporting the feature would be comparable to not supporting it because it is an error condition? How many users regularly request the ability to specify a lambda expression or expression tree in a custom attribute, and what are the difficulties and downsides of implementing it?Anonymous
June 06, 2010
Why don't you just implement propertyof(Person.Age)? That should be easy to do and so much useful. If it is hard for methods, don't do it, 99% people want infoof for properties anyway!Anonymous
August 30, 2010
I show on my blog how I use a now classic solution based on expression trees as an alternate solution: weblogs.asp.net/.../PropertyOf-INotifyPropertyChanged-PropertyChanged-strings-infoof.aspxAnonymous
May 03, 2011
"Observation: I think the real reason people want an infoof operator is that they don't want to use reflection, even though what they're asking for is available via reflection. That seems to stem from reflection being, well, confusing to use, and a little unwieldy. " No. It's because it's a RUN TIME mechanism, when what is really needed is a COMPILE TIME one.Anonymous
May 03, 2011
The comment has been removedAnonymous
January 10, 2012
I wonder if WPF dependency properties would have used infoof(Stuff) instead of a static "StuffProperty" had it been available. Settings like one-way vs two-way would have been neatly described in attributes and everything would have been rosy and gorgeous. What a shame we've missed that chance forever.Anonymous
January 10, 2012
I don’t understand the relevance of accessibility. typeof() is already limited to accessible types. Surely infoof() should, too. Anything else would make no sense in the context of the existing language.Anonymous
February 03, 2012
The comment has been removed