Access method via instance and static - c#

Is it possible to create a class that has a method definition where the method can be accessed statically, and also be accessed via an instance of the class, without having to have two separate names for the method or a separate set of arguments to distinguish the methods as two different methods.
i.e.
public class MyClass
{
public static int GetMyInt()
{
return 1;
}
}
...
MyClass classInst = new MyClass();
int i = MyClass.GetMyInt();
int x = classInst.GetMyInt();
Is this possible in C#? If so, how so?

No. A method is static or is not.
I don't a valid use case you want to allow calling a static method against an instance of a class.

I dont think you can have the cake and eat the cake too.
Static (methods which are called through class) and non-static (methods which are called through instance of class ) are two opposite sides of a coin.
So either it is static or non-static but not both

A static (or class) method is by definition different from an instance method.
An instance method is only accessible when you create an instance of that class;
A static method is always accessible, since it doesn't require class instanciation (provided it is public), at least always accessible within the class itself. You should know, however, that if you have a static variable, any changes made to that variable will affect the class, and have an impact everywhere that variable is used on the application.
eg.
...
static int lastId;
public static int getLastId(){
return lastId++;
}
This is a way you may control an autonumber on a class, since whenever you call getLastId, lastId will be incremented and that is valid for all the application.
edit
the sample code illustrates what happens with a static variable. That said, you should know that overloading is supported on c#. What you cannot have is a pair of methods with the same name tag and the same set and type of parameters.
for eg., this builds ok.
public static int getValue()
{
return 1;
}
public int getValue(int x)
{
return x * 1;
}
but this will throw an error:
public static int getValue(int z)
{
return 1;
}
public int getValue(int x)
{
return x * 1;
}
that is true independently of wether there is a static method or not. This will also generate a compile time error:
public int getValue(int z)
{
return 1;
}
public int getValue(int x)
{
return x * 1;
}
even this will give you an error:
public string getValue(int z)
{
return 1;
}
public int getValue(int x)
{
return x * 1;
}
so, yes, you may have a static method with the same name tag of an instance method, but you may not have the same set and type of parameters.
If you want both static an instance methods to have the same behaviour, then why do you need the intance method really? The static method will do the trick (considering you know the consequences of having a static method and its implications).

Nope. But you can wrap it. But will have to give it a new signature.
public int getMyInt()
{
return GetMyInt();
}

Related

Is it possible to assign to a (public or private) class member an initial value using a static method from another class?

say I have the following class
public class MyClass1 {
protected static int MyIntName1 = 0;
public static int GetMyIntName1() {
return MyIntName1;
}
public void MyMethod1() {
MyIntName1 += 1;
}
}
I then have a second class which has a private static int member for which I want to assign as initial value the value of MyIntName1 of the first class. Is there a way to do that ? Does the fact of being private or public make any difference actually ? I tried to do the following
public class MyClass2 {
private static int MyIntName2 = MyClass1.GetMyIntName1(); /* Here the value of MyIntName2
is assigned 0 not matter which value MyIntName1 could have */
public void MyMethod2() {
MyIntName2 = MyClass1.GetMyIntName1(); /*If I do this then MyIntName2 gets
the value of MyIntName1 but that holds only in this method and I would have to
repeat this in any other method of this class that requires the value of MyIntName1...*/
}
}
but no value is assigned to MyIntName2. However, if I do the same inside of a method of the second class, the value of MyIntName1 is assigned but that would only hold in that particular method. To be honest, I am not even sure that what I am trying to achieve makes any sense since I already have a static method which I am trying to assign at declaration to another static member inside a different class. It may be that there is no real purpose in doing this as I could just use the getter method from MyClass1 wherever I need it... However, I am wondering which are all the possibilities of assigning an initial value to class member. Forgive me if the question has already been asked of this does not make any sense.
Thank you.

Property setter not accessed when the property changed by external class

I have a public class that is is used to create a dll. It has a variable and a property. Let`s assume it looks like this:
public class Main
{
private int _someInt = 0;
public int SomeInt
{
get { return this._someInt; }
set
{
this._someInt = value;
if (this._someInt == 1)
{
_someInt = 0;
}
}
}
public int ExecuteMain()
{
OtherClass.DoSomething(this.SomeInt);
}
}
I also have another class, in a separate project in the OtherClass class, that has the static DoSomething method:
public static void DoSomething(int someInt)
{
someInt = 1;
}
My problem is that SomeInt property in the Main class is getting set to 1 by the DoSomething method of OtherClass, but this does not trigger the setter in the Main class' property. Am I doing something wrong?
What you are doing is passing SomeInt by value to the DoSomething method, which gets a copy of the int and just changes its local value.
You can:
Pass by ref: public static void DoSomething(ref int someInt)
Pass the Main class and change the value inside DoSomething:
public static void DoSomething(Mainclass main)
{main.SomeInt = 1}
There is no way of doing this,even if you pass the field by reference using ref keyword it's not gonna work because your property has a setter method not your field.You should be changing the value of your property, in order to execute the setter method and perform the validation.
You can do that,passing the current instance of your class instead of the field, for example:
public int ExecuteMain()
{
OtherClass.DoSomething(this); // just pass current instance using 'this'
}
public static void DoSomething(Main obj)
{
obj.SomeInt = 1;
}
If you want to have it invoke the setter logic, one option is to do something like this:
public static void DoSomething(Action<int> setSomeInt)
{
setSomeInt(1);
}
then call it like this:
public int ExecuteMain()
{
OtherClass.DoSomething(x => this.SomeInt = x);
}
The concept here is that what you're really giving the method is not a variable that can be set, but rather an action that can be performed. This is an important distinction, as setting a property is really a kind of action, which can have an arbitrarily complex implementation. This approach is a bit awkward in practice, though, so you'll want to think carefully about what you're really trying to do here and whether there's a better way to express the desired dependency.

Help with incrementing intergers when looping in C#

I have declared an int e.g. int i;
I have a method that is looped:
public static void NumberUp(int i)
{
i++;
System.Console.WriteLine(i);
...
}
although each time the number is returned, it is always 1. Not 1,2,3 and so on..
I would have imagined that "i" increases by one which each run of the method?
You can pass the variable by reference.
public static void NumberUp(ref int i)
{
i++;
System.Console.WriteLine(i);
...
}
This, however is bad design, as you now have a method with a side effect on the passed in parameter (which the method name doesn't indicate) - something that can catch other programmers by surprise.
It would be a better design to return the incremented value:
public static int NumberUp(ref int i)
{
return i + 1;
}
It's doing that because you're passing it by value. That means the variable within the function is a copy of the original.
If you want changes to reflect back to the original variable, you need to pass it by reference, meaning the variable refers to the original rather than a copy. You can use something like:
public static void NumberUp (ref int i) {
i++;
System.Console.WriteLine(i);
}
It would be better to define NumberUp like this
public static int NumberUp(int number)
{
System.Console.WriteLine(++number);
return number;
}
Then assign the return value in your loop.
int is a value type and not a reference type. As such, i inside NumberUp is a copy of the parameter you passed in.
If you want the value to be changed outside the method, pass the parameter as reference:
public static void NumberUp(ref int i)
This is reference vs value type. To accomplish what you actually need, you have to pass i by reference.
The Method is static but this does not automatically mean the parameter is.
Maybe use a static int in you class as member.
class x
{ static int i;
Or pass it byRef

Why does setting the property in the constructor of a struct not work?

I have following code which is not allowed (error below), why?
struct A
{
private int b;
public A(int x)
{
B = x;
}
public int B
{
get { return b; }
set { b=value; }
}
}
I receive the following error:
The 'this' object cannot be used before all of its fields are assigned
to Field 'Test.x' must be fully assigned before control is returned
to the caller
A struct's variables all have to be definitely assigned before you can use any methods or properties. There are two possible fixes here:
1) You can explicitly call the parameterless constructor:
public A(int x) : this()
{
B = x;
}
2) You can use the field instead of the property:
public A(int x)
{
b = x;
}
Of course the second option only works in your current form - you have to use the first option if you want to change your struct to use an automatic property.
However, importantly, you now have a mutable struct. This is almost always a very bad idea. I would strongly urge you to use something like this instead:
struct A
{
private readonly int b;
public A(int x)
{
b = x;
}
public int B { get { return b; } }
}
EDIT: More details of why the original code doesn't work...
From section 11.3.8 of the C# spec:
If the struct instance constructor doesn't specify a constructor initializer, the this variable corresponds to an out parameter of the struct type
Now initially that won't be definitely assigned, which means you can't execute any member function (including property setters) until all the firsts of the struct being constructed have been definitely assigned. The compiler doesn't know or try to take account of the fact that the property setter doesn't try to read from another field. It's all in aid of avoiding reading from fields which haven't been definitely assigned.
Change your constructor to:
public A(int x) :
this()
{
B = x;
}
As to "why", refer to 11.3.8 Constructors and 5.3 Definite assignment.

Meaning of "this" for a struct (C#)

According to MSDN (Section 11.3.6 of the C# spec):
Within an instance constructor of a
struct, this corresponds to an out
parameter of the struct type, and
within an instance function member of
a struct, this corresponds to a ref
parameter of the struct type. In both
cases, this is classified as a
variable, and it is possible to modify
the entire struct for which the
function member was invoked by
assigning to this or by passing this
as a ref or out parameter.
I don't get it. How is this different for a struct than for a class? Code examples are appreciated
Eric Lippert had a fabulous post on mutating readonly structs a while back that will really help clarify the issue for you. There's even a code example, and a quiz!
The salient point is that structs obey value semantics and classes do not and so this must mean something different for the two. this is readonly for a class, but not for a struct. The following code is legal
struct Point {
public int x;
public int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public void DoGoTime() {
GoTime(ref this);
}
public static void GoTime(ref Point p) {
p.x = 100;
p.y = 100;
}
}
but is not if "struct" is replaced by "class."
When you're dealing with structs, you're dealing with value types.
In a class, "this" is a reference to the current instance. This lets you mutate the class instance by setting properties/fields on the class.
However, if you're in a struct, things act differently. When you're in a struct's method, "this" lets you mutate the struct. However, if you're using this in a method, you're almost always dealing with a copy of the "original" struct.
For example:
struct Test
{
int i;
void Mutate() {
this.i += 1;
}
}
When you use this:
void MutateTest(Test instance)
{
instance.Mutate();
}
{
Test test = new Test();
test.i = 3;
Console.WriteLine(test.i); // Writes 3
test.Mutate(); // test.i is now 4
Console.WriteLine(test.i); // Writes 4
MutateTest(test); // MutateTest works on a copy.. "this" is only part of the copy itself
Console.WriteLine(test.i); // Writes 4 still
}
Now, the stranger part - this is valid, and what that quote was saying:
struct Test
{
public Test(int value)
{
this.i = value;
}
int i;
void Mutate(int newValue) {
this = new Test(newValue); // This wouldn't work with classes
}
}
///
{
Test test = new Test();
test.i = 3;
Console.WriteLine(test.i); // Writes 3
test.Mutate(4);
Console.WriteLine(test.i); // Writes 4
Jason's answer and Eric's post show one aspect of this which is interesting... but there's another which is even more alarming:
You can reassign this within a method, even if the type is otherwise immutable.
To demonstrate it, we'll use a struct which is stored in a non-readonly variable, but which contains a readonly field:
using System;
public struct LooksImmutable
{
private readonly int value;
public int Value { get { return value; } }
public LooksImmutable(int value)
{
this.value = value;
}
public void GoCrazy()
{
this = new LooksImmutable(value + 1);
}
}
public class Test
{
static void Main()
{
LooksImmutable x = new LooksImmutable(5);
Console.WriteLine(x.Value);
x.GoCrazy();
Console.WriteLine(x.Value);
}
}

Categories

Resources