I recently learned that any object with a GetAwaiter method returning an awaiter can be await-ed. This is true even if it's an extension method, meaning basically any object can be made await-able, if you so choose.
But is there a way to tell at runtime if an object is await-able? Normal reflection won't work, since it doesn't list an object's extension methods.
I don't have a particular need in mind when asking this question, I'm just curious if it's possible.
It's not possible because the information that the C# compiler uses to make that decision is gone.
In order to resolve extension methods we need to know the namespaces that are imported. That information is not available at runtime. It is a C#-only concept. The CLR does not know what a using is.
I cannot think of any reason you would want to see if an object is possibly awaitable at runtime because you can't act on that information. Maybe you could check if the object is a Task instead?
Related
I am new to C# and was trying to write an SNTP server on the weekend.
During the course of this development I ended up with exactly the same question as this one: How to use generics to pass argument to a non-generic method?
The question, repeated here is: "How to use generics to pass argument to a non-generic method?" The crucial answer to this question was that the non-generic method in question didn't have an overload which accepted an Object.
Now the question I have is a follow on question: why is Generics implemented this way? Or to rephrase, why are constraints required at all?
My understanding so far is that generics help to preserve compile time type safety which means that the compiler knows what types are being dealt with at compile time.
Why wasn't C# (or perhaps this question should pertain to the CLR) implemented such that the compiler can accept the fact that a generic class/method is being created in which an argument can be provided which may not be acceptable in all cases. Then, when the generic class/method get's invoked, the compiler can see the issue and complain at that time.
Is this a technical limitation?
It just seems like a real pity that a generic method cannot be created to wrap a non generic method with multiple overloads. Unless I opt to defer type checking to run time which is the solution to the aforementioned question, I would have to wrap this overloaded method with a suite of methods, one for each signature, even though the code within it will look identical. This would have been an ideal place to leverage a generic method.
The person who can best explain this is Eric Lippert, and he did, in What’s the difference, part one: Generics are not templates:
We do the overload resolution once and bake in the result. We do not change it at runtime when someone, possibly in an entirely different assembly, uses string as a type argument to the method. The IL we’ve generated for the generic type already has the method its going to call picked out. The jitter does not say “well, I happen to know that if we asked the C# compiler to execute right now with this additional information then it would have picked a different overload. Let me rewrite the generated code to ignore the code that the C# compiler originally generated...” The jitter knows nothing about the rules of C#.
[...]
Now, if you do want overload resolution to be re-executed at runtime based on the runtime types of the arguments, we can do that for you; that’s what the new “dynamic” feature does in C# 4.0. Just replace “object” with “dynamic” and when you make a call involving that object, we’ll run the overload resolution algorithm at runtime and dynamically spit code that calls the method that the compiler would have picked, had it known all the runtime types at compile time.
So why not: because the runtime wouldn't know how to re-generate the required code.
And something about a design philosophy that your code should fail as early as possible, preferably during compile time, but I can't find that quote right now.
I'm using ASP.NET and I know that I can mark a method as:
Obsolete
Not for future use
But I'm asking if I can mark a method as "Not yet used", that means "I wrote it but actually it is unused, sooner or later someone will using it".
Thanks!
You can throw a NotImplementedException with a appropriate message in your method. This will ensure during runtime that the method is not called.
public void MyMethod(){
throw new NotImplementedException("This will be implemented soon");
}
If you want to use metainformation you can define your own Attribute to decorate your methods. (But I think you can also reuse the ObsoleteAttribute with a special message)
No, you cannot. And it doesn't make much sense to do so.
Visual Studio 2015 does show you the method usage inside your current project, which is an indicator for 'dead' methods:
I assume you want it for a future functionality that currently is not active because is not fully implemented (is the only case I can imagine that make sense).
If you don't want it to be used don't put it in the interface (you should use interfaces) or put it in a distinct one that only you have. You can also use the Obsolete decorator with a "this is not meant to be used yet" message.
If anyone can use it because it's public and released you should not care about how many references it has. Usually you can't know it if the references are from outside your solution. You should not delete such a method because that is a breaking change.
If it's private your IDE should warn you and you can delete it or comment its future usage; add a reference to the functionality it is meant for so you can delete it in case it is closed (someone decides that is not going to be implemented).
This is managed by the NotImplementedException and can be very usefull when implementing interfaces where you know the members you need in the future but don´t want to implement them right now. Any user of the method will get the exception, however if you need a compile-time flag you´d be off by using the Obsolete-attribute together with a meaningul message such as "This method is not yet implemented" and the exception inside.
Just because you can doesn't mean you should....
Why write code that's not yet used?
That's like taking thermal underwear to the Sahara in case of a cold snap, when you're only visiting during the day.
While you can throw a NotImplementedException this won't give you compile time safety - it will just throw this exception on run time.
You can express all of your sorrow about the unused method in the Documentation Comment for this method. Just don't throw any NotImplementedException's or else this method isn't going to be used ever.
This is kinda dumb though, you should remove it if it is not used. As practice shows, most of the 'Not yet, but maybe some day' code is not going to ever be used at all, so it makes perfect sense to remove it. If for some reason you later need the method, you can always check your source control for that.
If you would like to litter your solution even more though, you can always do something stupid like implement your custom [PleaseUseMe]Attribute
I have a number of MethodBase instances referencing different open generic methods (expected), e.g. representing the following methods:
T Foo<T>(T nevermind, T other);
T Foo<T>(string nevermind, T other);
And I have a single MethodBase instance referencing closed method that was actually called (actual), e.g.:
int Foo<int>(string nevermind, int other);
How can I programatically check if actual closed method could match any of given expected open methods, especially when considering all the generics pitfalls and complications?
Specifically, I would like to identify that the correct item from expected list for given actual closed method is T Foo<T>(string nevermind, T other); and not the second one.
Moreover, for MethodBase corresponding to double Foo<double>(double something, string other) I'd like to have no results matched.
Is iterating through candidate methods and checking if each parameter from expected is assignable from corresponding actual parameter a good way? If so, is it the simplest way? Do I need to consider any special cases to not match methods that will not be chosen according to method overloads resolution rules in .NET?
Tl;dr. The problem is not possible to solve using reflection, at least as I understand it, and without more specificity..
Method resolution rules are extremely complicated, especially for generic methods. There are many pitfalls you will fall into. You will need to know not only the method, the type parameter, but also a lot of information about the target, along with its own type parameters. In some cases, where the method was called from.
Method has implementation in a base class but is hidden by the child.
Method is from an interface, and was implemented explicitly, and may have another method with the same name on the implementer.
A methods such as Foo<T>(T a, string other), Foo<T>(string a, T other), Foo<T>(string a, string other) and some other variations cannot be disambiguated for T = string unless you know where the call is coming from (these are legal methods, and the one that gets called depends on several things).
Generic constraints can be placed on methods.
Polymorphism on the argument types, including generic variance for interfaces and delegates.
Optional parameters.
This goes on and on.
Basically, it can never work. Not using reflection. Not the way you're proposing. Even if you have restrictions about what calls can be made, you'd have to decide which things to check and which not, and you will always miss a few. These aren't the only pitfalls by the way, just a random sampling.
However, you do have some options.
The first, and best option in my opinion, is going a step back and thinking about the original problem. Post that if you can. It might have a different answer, and people will be able to advise you better. Hopefully it's less complicated to understand.
If you limited the scope of the matter greatly, such as no generic constraints, no interfaces, and so forth, this might be possible. It would be error prone, because there are lots of gotcha's.
You can try resolving it at runtime using dynamic binding, but the way dynamic binding resolves methods may be different from the way it normally happens. I don't know much about this, though.
You can hook the runtime and also investigate method calls as they are resolved. There are libraries for this. This will even allow you to understand how late binding is resolved.
Finally, you can look into the IL, possibly with the aid of various tools and libraries such as Mono.Cecil. In the built library, method resolution has already been performed, so you will see exactly which methods are called from which locations. This doesn't sound feasible however.
Oh, there is Roslyn, and other compilers with interfaces. They already have the resolution logic implemented, so they may make the task easier. IF they are open source, you can try to understand how method resolution is performed there. I'm kind of out of my depth here, though. And I suspect it's not feasible.
I don't like posting links to specific libraries because I'd rather you just research them. Also because there are many options.
To summarize, at least in my opinion, and as I understand the problem, without great restrictions on the methods and more information, it is impossible.
I have a Web solution which contains two projects (A and B) with B referencing A.
In A I have an Html extension method that obviously can be called from either A or B.
My question is once the method is called (usually from a partial view) is there a way inside the method to figure out whether the call came from Assembly A or Assembly B without passing anything to it?
I tried to see if I can do anything with HttpContext.Current.Request but could not find anything useful. I can get the URI but that still does not tell me which assembly the file that originated the Request is in.
Thanks for your answers - the method returns a string and the string is from a string.resx file which I have one for each assembly. That is why I need to know which file to access to return the string. Since each assembly "registers" itself on start up if I add a new assembly my method will not change, since it will just look up the assembly.In fact my whole project will not change. The reason why I am not introducing another parameter at this time is b/c it will mean a HUGE amount of changes and I honestly don't see the benefit. While I see your point and I generally agree with it I think in my case it's not that the method returns different things , it's just grabbing the correct resource file based on the assembly.
As SLaks pointed out, you can check HttpContext.Current.Application.GetType().Assembly.
However I agree with John in the comments that you have probably made a bad design decision if you need this.
The Problem
Your method is a hypocrite.
It talks different to different callers but doesn't tell it in open.
You see, each method defines a certain contract with arguments and a return type.
For example, int.Parse says that it takes a string and turns it into an int. If we want to change default behavior, we may also give it NumberStyles and/or IFormatProvider.
We the consumers don't know how int.Parse is implemented. Because it is static, we most certainly expect it doesn't have side effects and will always return the same value for the same set of parameters.
Repeat this mantra after me:
Explicit is better than implicit.
You would probably be very angry if you found out int.Parse somehow analyzes your code and changes its behavior depending on where it's called from.
It's the caller's responsibility to define the context, not the callee's.
Try to give simple and concise answers to questions below:
What happens if the method is called from assembly C?
How would you unit-test it? What if some other developer uses this method in unit tests?
What happens if you rename assembly A or B? Merge them? Split them further?
Will you remember to change this method if anything above happens?
If answering any of the questions above clearly poses a challenge for you, it is a sign you're Doing It Wrong™.
Instead you should...
Introduce a Parameter
Think about the method contract. What can you do to make it full and descriptive?
Define a generic (as in English) method in a separate assembly that doesn't know anything about the callers and has additional parameters, and define parameter-filling shortcuts for it in concrete assemblies.
It's better that these parameters don't know anything about the assemblies either.
For example, if you needed to resolve URLs inside your method, you could accept string baseUrl or Func<string, string> urlResolver so it's potentially usable from any assembly that cares to specify those.
In the worst case, you could define an enum with possible caller contexts and pass it to the method. This will make your design problem explicit, rather than implicit. Obvious problem is always better than hidden problem, although worse than no problem at all.
Check HttpContext.Current.Application.GetType().Assembly
I have recently started to make useful use of C# extension methods. The SO examples and the documentation suggest that they are only used for instance methods (i.e. with the this keyword). It is possible to use them (or another approach) with static/class methods?
(My particular requirement is converting Java code to C# where "most of the code" does not need editing. The Java instance methods (e.g. Java String.indexOf()) can be routed through an extension method calling C# string.IndexOf()). I would like to do the same for, say, Java Math.abs() => C# Math.Abs()).
SUMMARY No. The answers suggest it would be a reasonable thing to have but it's unlikely to happen soon. Workarounds will require editing creating new classes or something similar and may not be worth it.
You cannot create static extension methods - it's also something I've wished to be able to do!
You could create your own static classes with a standard suffix, i.e. MathJSyntax.abs(..) which would call Math.Abs(..)
C# 3.0 does not allow the creation of static extension methods, unfortunately. F# however does allow this, along with the much desired feature of extension properties.
The notation itself doesn't let you do it, the "this" class parameter expects an instance to the class to be passed in. If they intended to at least eventually add it, they wouldn't have written it like that.
So the short answer is nope, and never will be!