c# cannot declare static and non static methods with same parameters? - c#

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.

Related

Provide extension method for types derived from `this` type

I've read this similar question I don't expect the same behavior as the OP and I don't really understand him but I have a usage for protected members inside the derived classes.
In Why is the 'this' keyword required to call an extension method from within the extended class Eric Lippert wrote:
... If you are in the scenario where you are using an extension method
for a type within that type then you do have access to the source
code. Why are you using an extension method in the first place then?
... Given those two points, the burden no longer falls on the language
designer to explain why the feature does not exist. It now falls on
you to explain why it should. Features have enormous costs associated
with them.
...
So I will try to explain why I would expect a behavior and it's usage example.
The feature:
A programer can access protected member of this object inside extension method.
When a protected member is used within extension method, you can only use the method inside classes derived from type of this object.
Protected extension method can be called only with this argument object which is the same object that is accessible by this keyword in caller method.
Real life usage scenario:
I'm playing with creating a Visual Studio custom editor based on WPFDesigner_XML example.
Currently I'm trying to figure things out in class with following signature:
public sealed class EditorPane : WindowPane, IOleComponent, IVsDeferredDocView, IVsLinkedUndoClient
{...}
Lot of methods are using services Like this:
void RegisterIndependentView(bool subscribe)
{
IVsTextManager textManager = (IVsTextManager)GetService(typeof(SVsTextManager));
if (textManager != null)
{
if (subscribe)
{
textManager.RegisterIndependentView(this, _textBuffer);
}
else
{
textManager.UnregisterIndependentView(this, _textBuffer);
}
}
}
I like to keep focus on things that actually matter so I wrote helper method to simplify such methods. For example:
private void RegisterIndependentView(bool subscribe) {
if (with(out IVsTextManager tm)) return;
if (subscribe) tm.RegisterIndependentView(this, _textBuffer);
else tm.UnregisterIndependentView(this, _textBuffer);
}
The with method look like this:
private bool with<T>(out T si) {
si = (T)GetService(getServiceQueryType<T>());
return si == null ? true : false;
}
And I placed getServiceQueryType<T>() in a static class:
public static class VSServiceQueryHelper {
public static Type getServiceQueryType<T>() {
var t = typeof(T);
if (!serviceQueryTypesMap.ContainsKey(t)) throw new Exception($#"No query type was mapped in ""{nameof(serviceQueryTypesMap)}"" for the ""{t.FullName}"" interface.");
return serviceQueryTypesMap[t];
}
private static Dictionary<Type, Type> serviceQueryTypesMap = new Dictionary<Type, Type>() {
{ typeof(IVsUIShellOpenDocument), typeof(SVsUIShellOpenDocument) },
{ typeof(IVsWindowFrame), typeof(SVsWindowFrame) },
{ typeof(IVsResourceManager), typeof(SVsResourceManager) },
{ typeof(IVsRunningDocumentTable), typeof(SVsRunningDocumentTable) },
{ typeof(IMenuCommandService), typeof(IMenuCommandService) },
{ typeof(IVsTextManager), typeof(SVsTextManager) },
};
}
This works well but I would also like to place the with method inside VSServiceQueryHelper as an extension so any time I would extend WindowsPane i could just place using static com.audionysos.vsix.utils.VSServiceQueryHelper; at the top and use the with method that is already implemented.
The problem:
I can't make with method an extension because the GetService method used by it is a protected member of the WindowsPane which is the base type of my class. So now I need to place with implementation in every class that extends WindowPane and this breaks the rule of never repeat yourself :/
A simple solution would be to create a base class containing the With method.
If that is too burdensome, then you can also implement this using Reflection to invoke the GetService method from the extension method. In fact, we can create a delegate to it that will ensure there is minimal overhead to invoking With many times.
internal static class WindowPaneExtensions
{
private static readonly Func<WindowPane, Type, object> WindowPaneGetService = CreateWindowPaneGetService();
public static bool With<T>(this WindowPane pane, out T service)
{
service = (T)WindowPaneGetService(pane, GetServiceQueryType<T>());
return service != null;
}
private static Func<WindowPane, Type, object> CreateWindowPaneGetService()
{
var method = typeof(WindowPane).GetMethod("GetService", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(Type) }, null);
var del = (Func<WindowPane, Type, object>)method.CreateDelegate(typeof(Func<WindowPane, Type, object>));
return del;
}
}
I think your proposal to allow certain extension methods access to protected members is a non-starter. For example, the following is not allowed:
public class MyPane : WindowPane
{
public static void Test(WindowPane p)
{
var service = p.GetService(typeof(Service));
// etc.
}
}
But you ask, "Isn't it allowed to access base class members from a derived class?" No, that actually isn't the rule. The rule is that you can access base class members from derived class only via a reference to the derived class, not from any base class reference directly. More details on this here. Your proposal amounts to allowing this kind of thing for an even larger class methods (i.e. methods that some other library author declares to be extension methods). Eric Lippert has written about this issue (here and here) in the past as well. Since cross hierarchy calls are blocked by the CLR, I would not expect something like this proposal to get implemented any time soon.

Determine if function call is static

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.
}
}
}

Static/Instance methods and extension questions

I'm new to C# and I began working on a project that needed a method added to a class in C#. I found myself re examining the differences between static and instance methods and I'm unable to explain the following in a sample project.
My Core object:
namespace ExtendingObjects
{
public class MyCoreObject
{
public String name;
public String returnName()
{
return name;
}
}
}
My attempt to extend the object:
namespace ExtendingObjects
{
public static class Extensions
{
public static void addName(this MyCoreObject mco, String str)
{
mco.name=str;
}
public static String getName(this MyCoreObject mco)
{
return "test";
}
}
}
Calling program:
namespace ExtendingObjects
{
class Program
{
static void Main(string[] args)
{
MyCoreObject co = new MyCoreObject();
co.addName("test");
//Static method seems to work with instance?
String n = co.returnName();
Console.WriteLine("The name is " + n);
Console.ReadLine();
//Does not work
//Static method from a type
//String n2 = MyCoreObject.getName()
}
}
}
It was my understanding that static items stayed with the class and instance items with the instance per MSDN Static and Instance Members. However, I seem to be able to access a static method through an instance above, but not able to access a static method through a type.
Why does co.returnName() work and not MyCoreObject.getName()? I would think they would be reverse based on my reading. How can I make the getName() method available without instantiating the object first?
Thanks in advance.
Your two methods are extension methods, which are meant to look like instance methods when they're called. They can be called statically, but you need to supply the instance as the first argument, and specify the class which declares the extension method, not the type that the method "extends":
Extensions.getName(co);
When you call an extension method "as" an instance method, it's just a compiler trick. So this code:
co.addName("test");
is compiled to the exact equivalent of:
Extensions.addName(co, "test");
(As an aside, you would do well to start following normal .NET naming conventions as soon as possible. The earlier you get in the habit, the better.)

Can I use some other class's function as a delegate?

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.

Static property references non-static method

How can a static property reference a nonstatic method?
Example:
public static int UserID
{
get
{
return GetUserID();
}
}
private int GetUserID()
{
return 1;
}
When I try to compile this, I get the error: "An object reference is required for he non-static field, method or property "GetUserID()"
This doesn't work.
When you define a static property (or static method), you're defining a property that works on the class type, not on an instance of the class.
Instance properties and methods, on the other hand, work upon a specific, constructed, instance of a class. In order to use them, you need to have a reference to that specific instance. (The other way around, however, is fine.)
As an example, think of Fruit, and an "Apple" class. Say the apple class has an instance property that is how ripe the Apple is at this point in time.
You wouldn't as "Apple" to describe how ripe it is, but rather a specific "Apple" (instance). On the other hand, you could have an instance of an apple, and ask it whether it contains seeds (which might be defined on the Apple class itself (static)).
You'll just have to create a new instance:
public static int UserID
{
get
{
return new MyClass().GetUserID()
}
}
Well, you don't have to create a new instance every time UserId is called -- you can have a static field containing an instance of MyClass instead (which of course would be an approach toward implementing the Singleton pattern).
Although you can read that your static property is calling a method that could be made static, the other method isn't static. Thus, you must call the method on an instance.
You need somehow to get an instance. Without an instance, it's impossible to call an instance method.
For your case, are you sure that you need GetUserID() to be an instance method? It returns anyway the same value. Or, if your code is just dummy, and you require more logic in GetUserID(), maybe you can tell us what you intend to do?
An easy way to think about it is the following: a non-static method (or property, because properties are just wrapped-up methods) receives, as a first hidden parameter, a reference to the instance on which they operate (the "this" instance within the called method). A static method has no such instance, hence nothing to give as first hidden parameter to the non-static method.
Simply it can't.
If you need to call a static method to invoke an instance method, probably you want a Singleton
Try look at:
http://en.wikipedia.org/wiki/Singleton_pattern
Example:
public sealed class Singleton
{
private static readonly Singleton _instance = new Singleton();
private Singleton() { }
public static Singleton Instance
{
get
{
return _instance;
}
}
public static int UserID
{
get
{
return _instance.GetUserID();
}
}
private int GetUserID()
{
return 1;
}
}

Categories

Resources