I have a function SerializeUser in the Class User.
This function does not have a Parameter.
I want to have different functionality in these two types of function calls:
User.SerializeUser(); //Do sth...
and
User u = new User();
u.SerializeUser(); //Do sth else...
Is it possible to check if it is a static function call or a non static function call?
No, a function cannot be both static and non-static.
What you can do is create two methods, one static, and one non-static, although they will need to have different signatures. If you want them both to accept no arguments, they will have to have a different name, which is likely for the best anyway; given that one is acting on an instance and another isn't, there is almost certainly something at least somewhat different about what the methods are doing that you should reflect in their name.
I think what you're confusing here is that if you define one method, SerializeUser() on your User object, you will not be able to call User.SerializeUser() unless it is static. If it is static, then you won't be able to do new User().SerializeUser() - you can only do both with two methods, same name or not, and you can only have the same name if you differentiate their signatures so the compiler can resolve which one to use.
The only way this makes sense as something you'd want to do is if the instance method passes the instance as an argument to the static method, and the static method accepts an instance as a parameter, i.e.:
namespace MyNamespace
{
public class MyClass
{
public static void Method(MyClass c = null)
{
if (c == null)
{
//Do Stuff From Static
}
else
{
//Do Different Stuff With Instance
}
}
public void Method()
{
Method(this);
}
}
}
You can also use something else to differentiate them, such as a boolean with a default value, or without a default value. Ex. if the static method has a bool flag = false parameter, then the instance method could call it with flag = true and then you can make the behavior differentiate. This is slightly nasty code, though, as it hides the method behind tricky overload resolution.
To answer your question directly you can check whether the current method is static with MethodBase.GetCurrentMethod().IsStatic, but I don't think that will actually be of use to you in this situation.
Looking at your code, though, I imagine what you want is this:
namespace MyNamespace
{
public class User
{
public static string SerializeUser(User u = null)
{
if (u != null)
return u.SerializeUser();
else
return "something"; //default(User).SerializeUser();?
}
}
public static class UserExtensions
{
public static string SerializeUser(this User u)
{
//return however you serialize your user.
}
}
}
Related
I'm not sure exactly how to call this situation, but here it is:
I have 2 methods with different types, but from the "outside" they have the same signature. And when calling the method, I would like to invoke a specific method instead of the other - here is what I have:
public class SomeClass
{
public async Task<Response<T>> MyMethod<T>(string name, T myObj)
{
// some code here
}
public async Task<Response<T>> MyMethod<T>(string name, string myObj)
{
// some code here
}
}
For the compiler, the 2 methods above are different and have different signatures. But when calling:
var myClass = new SomeClass();
myClass.MyMethod("name", "something");
When calling MyMethod in the example, what's being called is MyMethod<T>(string name, T myObj), but what I would actually want to call is the second method. Is there a way to make it call a specific signature?
EDIT:
I found the if I give in one of the methods a different name to the second variable and then calling the method with the variable name as part of the call it does work, as in the following example:
public class SomeClass
{
public async Task<Response<T>> MyMethod<T>(string name, T myObj)
{
// some code here
}
public async Task<Response<T>> MyMethod<T>(string name, string myNewObj)
{
// some code here
}
}
var myClass = new SomeClass();
myClass.MyMethod<AnyOfMyTypes>("name", myNewObj: "something");
While this works, following Jon's response below, does it seem like something that is correct to do? As far as for the method name, I would like to keep it the same, and the other option is to change the signature by adding some dummy boolean variable.
The compiler certainly can't call the second method with that calling code, as it wouldn't know what to infer for T. If you specify a type argument though, it does call the second method:
myClass.MyMethod<string>("name", "something");
While that will work, I would strongly advise you to change the design if you possibly can. Rename one of the methods. I can reasonably call myself a C# expert, but I couldn't predict from inspection whether or not that would work. The overload resolution and type inference details in C# are really complicated, and it's unreasonable to expect every C# developer to know them inside out.
If you can give the methods different names, the code code is likely to be a lot simpler to read.
Following Jon's answer I'd suggest following solution to your problem:
private async Task<Response<T>> MethodForString<T>(string str)
{
// some code...
}
public async Task<Response<T>> Method<T>(T obj)
{
if (typeof(T) == typeof(string))
return MethodForString<T>(obj as string);
// some code...
}
Above is just a sample, but idea is simple: just check type of T and call appropriate method :)
This way, all your method call will remain exactly the same :)
The reason the first method is being called is because you have a generic type of T.
If you pass a string into this then it will hit the first method. It is better design to only have one method. If you want to be able to pass in any type then keep the first method, if you want just a string then keep just the second method. You should only have two methods if both have distinct clear purposes.
This
public class SomeClass
{
public async Task<Response<T>> MyMethod<T>(string name, T myObj)
{
// some code here
}
}
Or
public class SomeClass
{
public async Task<Response<T>> MyMethod<T>(string name, string myObj)
{
// some code here
}
}
Or
public class SomeClass
{
public async Task<Response<T>> MyMethod<T>(string name, string myObj)
{
// some code here
}
public async Task<Response<T>> MyMethod<T>(string name, int age, string address)
{
// some code here
}
}
Dont put a dummy variable into any of the methods, this will lead to problems debugging and be misleading for other developers.
I'm trying to restrict the return type of a generic delegate without specifying the parameter signature, and I don't know how to do this, or if it is even possible.
How can I do this or is it impossible?
My research has come up dry. Some pseudo-C# code would probably help steer you toward what I'm trying to do:
public class SomeClass< T, U > where T : Delegate // returning U
{
private someDelegate;
public SomeClass( T someDelegate )
{
this.someDelegate = someDelegate;
}
public U Run()
{
return someDelegate.DynamicInvoke();
}
}
... Elsewhere
public delegate string aDelegate();
public static string SayHi()
{
return "Hello!";
}
aDelegate greeter = SayHi;
var something = new SomeClass< aDelegate, string>( greeter );
Console.WriteLine( something.Run() ); // Should write "Hello" to the console.
I know this is a rather contrived pseudo example. I aim for a more involved usage, of course. I'm trying to write a console menu class that would associate a list of given menu options with actions that would fire depending on what option the user chooses. Right now, it just returns the string the user chose from the menu. What I'd like be able to do is return what--if anything--the associated method returns. This could perhaps be returned with the user chosen option string in a tuple... But, I figured this mini-example just cut straight to the technical hurdle I'm experiencing.
Thanks!
.NET already defines a generic delegate that returns the generic argument as it's result, Func<T>. You don't even need to define it.
public class SomeClass<U>
{
private Func<U>;
public SomeClass(Func<U> someDelegate)
{
this.someDelegate = someDelegate;
}
public U Run()
{
return someDelegate();
}
}
There's no real useful reason to allow a user of the type to provide any arbitrary delegate of the same signature. Really I'd advise you to avoid using any delegates in your code other than Func and Action (with various different numbers of generic arguments) whenever possible, as it's just creating a hassle to do so. I would consider it a reasonable restriction on any caller that has a delegate of a different type but the same signature to simply convert it to a Func<T> anyway, it's not like it's even a difficult conversion for them.
If you don't want to use Func<T> (as Servy suggests), e.g. if you have a custom delegate of your own that you want to be passed with type-safety, then perhaps you can make your custom delegate generic with respect to its return type. Then you can do it this way:
public delegate T MyDelegate<T>();
public class Foo<T>
{
private readonly MyDelegate<T> _delegate;
public Foo(MyDelegate<T> handler)
{
_delegate = handler;
}
public T Bar()
{
return _delegate();
}
}
I got this class
public class fooBase
{
public List<MethodsWithCustAttribute> MethodsList;
public bool fooMethod([CallerMemberName]string membername =""))
{
//This returns a value depending of type and method
}
public void GetMethods()
{
// Here populate MethodsList using reflection
}
}
And This Attribue Class
// This attribute get from a database some things, then fooMethod check this attribute members
public class CustomAttribute
{
public string fullMethodPath;
public bool someThing ;
public bool CustomAttribute([CallerMemberName]string membername ="")
{
fullMethodPath = **DerivedType** + membername
// I need here to get the type of membername parent.
// Here I want to get CustClass, not fooBase
}
}
Then I have this
public class CustClass : fooBase
{
[CustomAttribute()]
public string method1()
{
if (fooMethod())
{
....
}
}
}
I need the Type name of the CallerMember, there is something like [CallerMemberName] to get the Type of class owner of the Caller ?
It isn't foolproof, but the convention with .NET is to have one type per file and to name the file the same as the type. Our tooling also tends to enforces this convention i.e. Resharper & Visual Studio.
Therefore it should be reasonable to infer the type name from the file path.
public class MyClass
{
public void MyMethod([CallerFilePath]string callerFilePath = null, [CallerMemberName]string callerMemberName = null)
{
var callerTypeName = Path.GetFileNameWithoutExtension(callerFilePath);
Console.WriteLine(callerTypeName);
Console.WriteLine(callerMemberName);
}
}
Caller member
Granted, getting the caller member name is not "natural" in the object model.
That's why the C# engineers introduced CallerMemberName in the compiler.
The real enemy is duplication, and stack-based workarounds are inefficient.
[CallerMemberName] allows to get the information without duplication and without ill-effect.
Caller type
But getting the caller member type is natural and easy to get without duplication.
How to do it
Add a "caller" parameter to fooMethod, no special attribute needed.
public bool fooMethod(object caller, [CallerMemberName]string membername = "")
{
Type callerType = caller.GetType();
//This returns a value depending of type and method
return true;
}
And call it like this:
fooMethod(this);
This answer the question
You stated
// Here I want to get CustClass, not fooBase
and that's exactly what you'll get.
Other situations where it would not work, with solutions.
While this exactly answers your requirements, there are other, different, cases where it wouldn't work.
Case 1: When caller is a static methods (there is no "this").
Case 2: When one wants the type of the caller method itself, and not the type of the caller itself (which may be a subclass of the first).
In those cases, a [CallerMemberType] might make sense, but there are simpler solutions.
Notice that the static caller case is simpler: there is no object so no discrepancy between it and the type of the calling method. No fooBase, only CustClass.
Case 1: When caller is a static methods (there is no "this")
If at least one caller is a static method, then don't do the GetType() inside the method but on call site, so don't pass "this" to the method but the type:
public bool fooMethodForStaticCaller(Type callerType, [CallerMemberName]string membername = "")
Static caller will do:
public class MyClassWithAStaticMethod // can be CustClass, too
{
public static string method1static()
{
fooMethodForStaticCaller(typeof(MyClassWithAStaticMethod));
}
}
To keep compatibility with object callers, either keep the other fooMethod that takes the this pointer, or you can remove it and object callers will do:
fooMethod(this.GetType());
You can notice that the typeof(MyClassWithAStaticMethod) above repeats the class name and it's true. It would be nicer to not repeat the class name, but it's not such a big deal because this repeats only once, as a typed item (not a string) and inside the same class. It's not as serious a problem as the original problem that the [CallerMemberName] solves, which was a problem of repeating the caller name in all call sites.
Case 2: When one wants the type of the caller method, not the type of the caller
For example, in class fooBase you want to call anotherFooMethod from object context but want the type being passed to always be fooBase, not the actual type of the object (e.g. CustClass).
In this case there is a this pointer but you don't want to use it. So, just use actually the same solution:
public class fooBase
{
[CustomAttribute()]
public string method1()
{
if (anotherFooMethod(typeof(fooBase)))
{
....
}
}
}
Just like in case 1, there is one repetition, not one per call site, unless you have an pre-existing problem of rampant code duplication, in which case the problem being addressed here is not the one you should worry about.
Conclusion
[CallerMemberType] might still make sense to avoid duplication at all, but:
anything added to the compiler is a complexity burden with maintenance cost
given the existing solutions I'm not surprised there are items with higher priority in the C# development team list.
See Edit 2 for the better solution.
The information that CompilerServices provides is too little in my opinion to get the type from the calling method.
What you could do is use StackTrace (see) to find the calling method (using GetMethod()) and get the type using Reflection from there.
Consider the following:
using System.Runtime.CompilerServices;
public class Foo {
public void Main() {
what();
}
public void what() {
Bar.GetCallersType();
}
public static class Bar {
[MethodImpl(MethodImplOptions.NoInlining)] //This will prevent inlining by the complier.
public static void GetCallersType() {
StackTrace stackTrace = new StackTrace(1, false); //Captures 1 frame, false for not collecting information about the file
var type = stackTrace.GetFrame(1).GetMethod().DeclaringType;
//this will provide you typeof(Foo);
}
}
}
Notice - As #Jay said in the comments, it might be pretty expensive but it does the work well.
Edit:
I found couple of arcticles comparing the performance, and it is indeed horrbily expensive comparing to Reflection which is also considered not the best. See: [1] [2]
Edit 2:
So after a look in depth on StackTrace, it is indeed not safe to use it and even expensive.
Since every method that will be called is going to be marked with a [CustomAttribute()], it is possible to collect all methods that contains it in a static list.
public class CustomAttribute : Attribute {
public static List<MethodInfo> MethodsList = new List<MethodInfo>();
static CustomAttribute() {
var methods = Assembly.GetExecutingAssembly() //Use .GetCallingAssembly() if this method is in a library, or even both
.GetTypes()
.SelectMany(t => t.GetMethods())
.Where(m => m.GetCustomAttributes(typeof(CustomAttribute), false).Length > 0)
.ToList();
MethodsList = methods;
}
public string fullMethodPath;
public bool someThing;
public CustomAttribute([CallerMemberName] string membername = "") {
var method = MethodsList.FirstOrDefault(m=>m.Name == membername);
if (method == null || method.DeclaringType == null) return; //Not suppose to happen, but safety comes first
fullMethodPath = method.DeclaringType.Name + membername; //Work it around any way you want it
// I need here to get the type of membername parent.
// Here I want to get CustClass, not fooBase
}
}
Play around with this approach to fit your precise need.
Why not just use public void MyMethod<T>(params) { string myName = typeof(T).Name }
then call it Logger.MyMethod<Form1>(...);
You avoid the performance hit of reflection, if you just need basic info.
If I try to declare static and non-static methods with the same parameters compiler returns an error: type 'Test' already defines a member called 'Load' with the same parameter types.
class Test
{
int i = 0;
public int I
{
get { return i; }
set { i = value; }
}
public bool Load(int newValue)
{
i = newValue;
return true;
}
public static Test Load(int newValue)
{
Test t = new Test();
t.I = newValue;
return t;
}
As far as I know these two methods can not be mixed, non static method is called on object whereas static method is called on class, so why does compiler not allow something like this and is there a way to do something similar?
If your Test class had a method like this:
public void CallLoad()
{
Load(5);
}
the compiler would not know which Load() to use. Calling a static method without the class name is entirely allowed for class members.
As for how to do something similar, I guess your best bet is to give the methods similar but different names, such as renaming the static method to LoadTest() or LoadItem().
Inside the class itself, you call both instance methods and static methods without an instance or the class name, thus making the two undistinguishable if the names and parameters are the same:
class Test
{
public void Foo()
{
Load(0); // Are you trying to call the static or the instance method?
}
// ...
}
The signature of a method is the combination of name and parameters (number and types).
In your case, your 2 methods have the same identical signature. The fact that one is static and other one is not makes no difference in accepting them as valid methods for the class.
I don't think so. if a non static method in this class calls Load(intValue). which method will be called?
Both methods have the same name, defined in the same class (scope) and with the same signature. C# does not allow this.
The problem is not related with writing this or the classname. C# specs allow you to call static methods using object instances:
AClass objectA = new AClass();
objectA.CallStaticMethod();
This code is valid so the compiler never has a way to know if you're calling a static or an instance method.
In C# a method cannot be overloaded by return type. It must at least have a different set of parameters, regardless if the method is static or not.
Say I have 2 classes, class A and class B. Class A creates an instance of Class B. Class A has a function that I would like to pass into a method from Class B.
class A {
void Main(string[] args) {
B classB=new B();
DelegateCaller(new delFunction(classB.TheFunction()); // <-- Won't compile (method name expected)
DelegateCaller(new delFunction(B.TheFunction()); // <-- Won't compile (object reference is req'd)
}
public delegate string delFunction();
public DelegateCaller(delFunction func) {
System.Console.WriteLine(func());
}
}
class B {
public string TheFunction() {
return "I'm Printing!!!";
}
}
I'm not sure if it a syntax issue or it's just something I can't do. Maybe I need to define the delegate in B, but reference it in A? What about B's this pointer?
It's just a syntax issue; get rid of the parentheses after classB.TheFunction - they indicate that you wish to invoke the method.
DelegateCaller(new delFunction(classB.TheFunction));
Do note that there is an implicit conversion available from a method-group, so you can just do:
DelegateCaller(classB.TheFunction);
Also note that creating your own delegate-type in this case is unnecessary; you could just use the in-built Func<string> type.
EDIT: As Darin Dimitrov points out, there is also the unrelated issue of calling an instance method as though it were a static method.
Try like this:
class A
{
static void Main()
{
B classB = new B();
DelegateCaller(classB.TheFunction);
}
public delegate string delFunction();
public static void DelegateCaller(delFunction func)
{
Console.WriteLine(func());
}
}
class B
{
public string TheFunction()
{
return "I'm Printing!!!";
}
}
Let me elaborate about the different changes I've made to your initial code:
TheFunction in class B needs to be public so that you can access it from class A
The DelegateCaller method in class A should be static and not necessarily return a value (declare it as void) if you want to call it from the static Main method.
The definition of the delFunction delegate should return a string.
Take the parenthesis off the end of TheFunction. You want the method, not the result of a call to the method.
If you want to capture an instance method for usage in a general purpose fashion you should use Delegate.CreateDelegate(Type,MethodInfo). This is nice as it allows you to create an "open delegate" meaning it isn't bound to an instance and can take any instance that is a ClassB. It makes reflection quite fast if you know the type information, as this method will perform much faster than the equivalent statement using MethodInfo.Invoke.
DelegateCaller(new delFunction(B.TheFunction());
Should be
DelegateCaller(new delFunction(B.TheFunction);
To use classB.TheFunction you would need to make TheFunction static. You pass in the function with no parens.