It seems that an extension method in C# cannot overwrite the original object. Why is that? Example:
using System;
namespace ExtensionTest
{
public class MyTest {
public string MyName { get; set; }
}
class Program
{
static void Main(string[] args)
{
var myTest = new MyTest() { MyName = "Arne" };
Console.WriteLine("My name is {0}", myTest.MyName);
// Will write "My name is Arne"
myTest.AlterMyTest();
Console.WriteLine("My name is {0}", myTest.MyName);
// Will write "My name is Bertil"
myTest.OverwriteMyTest();
Console.WriteLine("My name is {0}", myTest.MyName);
// Will write "My name is Bertil" (why?)
}
}
public static class ExtensionClass{
public static void AlterMyTest(this MyTest myTest)
{
myTest.MyName = "Bertil";
}
public static void OverwriteMyTest(this MyTest myTest)
{
myTest = new MyTest() { MyName = "Carl" };
}
}
}
Because as usual, reference of the class is copied while passing to the method, and you are assigning new object to the new reference.
For not-extension methods, you can pass reference by ref/out keywords
public static void Func(out MyClass b)
{
b = new MyClass();
}
...
MyClass b;
Func(out b);
Assert.IsNotNull(b);
but C# compiler doesn't allow to use ref with this(the reason is in David Arno's comment). You are free to remove this keyword, and call static method instead of extension.
Related
using System;
namespace Testing
{
class Program
{
static void Main(string[] args)
{ }
}
public class A
{
public void method1()
{ }
}
public class B : A
{
public void method2()
{ }
}
public class Test
{
A a = new A();
a.method1();
}
}
Please paste this code in VS and Please explain me why it is not in current context?
Inside a class is not the right place to call most functions:
public class Test
{
A a = new A();
a.method1();
}
Just put stuff into the main function, wich is there specifically for that part of the programming:
static void Main(string[] args)
{
A a = new A();
a.method1();
}
you can not have statements directly in class.
public class Test
{
A a = new A();
a.method1(); // this is not possible.
}
please modify your class as below:
public class Test
{
public void InvokeMethodOnA()
{
A a = new A();
a.method1();
}
}
or like this;
public class Test
{
A a = new A();
public void InvokeMethodOnA()
{
a.method1();
}
}
You can call method in body of method (sounds strange, but I don't have a better explanation).
In your case you mix a definition of the class Test with a context of function. I hope code with comments will be more descriptive:
public class Test
{
// this is not a local variable, this is a definition of field with initialization
A a = new A();
// you try call method on field, but in context of class definition, which is prohibited
a.method1();
}
I'm playing with VS. I'm a rookie, It must be basic. I have created 2 classes and I puzzled with result. I'm using Visual Studio 2015 community edition.
I'm expect to receive at console :
myfirstClass
Class
first.
mysecondClass
Class
second.
I received :
myfirstClass
Class
_
class Program
{
public class mysecondClass
{
static public string myName ;
public mysecondClass()
{
Console.WriteLine("mysecondClass");
myName = "Class";
}
public static void Display()
{
Console.WriteLine(myName);
}
~mysecondClass()
{
Console.WriteLine("second.");
}
}
public class myfirstClass
{
public string myName;
public myfirstClass()
{
Console.WriteLine("myfirstClass");
myName = "Class";
}
public static void Display()
{
myfirstClass d = new Program.myfirstClass();
Console.WriteLine(d.myName);
}
~myfirstClass()
{
Console.WriteLine("first.");
}
}
static void Main(string[] args)
{
myfirstClass.Display();
mysecondClass.Display();
Console.ReadLine();
}
}
This is not a bug in Visual Studio. I think you have got two concepts wrongly.
Firstly, the finaliser of a class will not be called immediately after the object is out of scope. It will be called at a random time. It is quite unpredictable.
Therefore, this:
Console.WriteLine("first.");
is not printed.
The second thing is that constructors of a class is only called when you write new XXX(...) (or through reflection). Just calling a static method will not invoke the constructor.
In other words, these lines are never executed:
Console.WriteLine("mysecondClass");
myName = "Class";
You never wrote new mysecondClass().
When this line in the display method of mysecondClass executes:
Console.WriteLine(myName);
Since myName has not been assigned, it is null, and so nothing is printed.
class Program
{
public class mysecondClass
{
public string myName { get; set; }
public mysecondClass()
{
Console.WriteLine("mysecondClass");
myName = "Class";
}
public static void Display()
{
var mySecond = new mysecondClass();
Console.WriteLine(mySecond.myName);
}
~mysecondClass()
{
Console.WriteLine("second.");
}
}
public class myfirstClass
{
public string myName { get; set; }
public myfirstClass()
{
Console.WriteLine("myfirstClass");
myName = "Class";
}
public static void Display()
{
myfirstClass d = new myfirstClass();
Console.WriteLine(d.myName);
}
~myfirstClass()
{
Console.WriteLine("first.");
}
}
static void Main(string[] args)
{
myfirstClass.Display();
mysecondClass.Display();
Console.ReadLine();
}
}
try this
Example:
String name = "setMethodName";
class Test
{
public void setName.[name] (Object o)
{
}
}
public static void Main()
{
Test test = new Test();
test.setMethodName(new Object());
}
I have a static member:
namespace MyLibrary
{
public static class MyClass
{
public static string MyMember;
}
}
which I want to access like this:
using MyLibrary;
namespace MyApp
{
class Program
{
static void Main(string[] args)
{
MyMember = "Some value.";
}
}
}
How do make MyMember accessible (without MyClass.) to MyApp just by adding using MyLibrary?
C# doesn't allow you to create aliases of members, only of types. So the only way to do something like that in C# would be to create a new property which is accessible from that scope:
class Program
{
static string MyMember
{
get { return MyClass.MyMember; }
set { MyClass.MyMember = value; }
}
static void Main(string[] args)
{
MyMember = "Some value.";
}
}
It's not really an alias, but it accomplishes the syntax you're looking for.
Of course, if you're only accessing / modifying a member on MyClass, and not assigning to it, this can be simplified a bit:
class Program
{
static List<string> MyList = MyClass.MyList;
static void Main(string[] args)
{
MyList.Add("Some value.");
}
}
I have two classes as follow:
First one:
class Class1
{
private void Method1()
{
var obj=new TestClass();
obj.TestMethod1();
}
}
Second One:
class TestClass
{
public void TestMethod1()
{
TestMethod2();
}
private void TestMethod2()
{
//get the calling class
}
}
When Class1.Method1 calls TestClass.TestMethod1 which in turn calls TestClass.TestMethod2, I want to get the fully qualified class name of Class1 inside TestClass.TestMethod2. I have seen this link, but I think I will get TestClass.TestMethod1 as method name and TestClass as the class name. How can I get the calling class name?
There is no nice way to do that. You can access the stack-frames (just look at the second frame, rather than the first) - but that is expensive and brittle. You could use optional caller-member-name attributes (being explicit from TestMethod1) to get hold of "Method1", but not the "Class1" part. One other option would be to pass in an object (or just the name) explicitly; for example:
private void Method1()
{
var obj=new TestClass();
obj.TestMethod1(this);
}
public void TestMethod1(object caller=null,
[CallerMemberName] string callerName=null)
{
TestMethod2(caller??this,callerName??"TestMethod1");
}
private void TestMethod2(object caller=null,
[CallerMemberName] string callerName=null)
{
string callerName = ((caller??this).GetType().Name) + "." + callerName
//get the calling class
}
but I have to confess that is pretty ugly
Perhaps better would be to question why you need this in the first place.
Could you not pass the type into the second class via constructor like:
class Class1
{
private void Method1()
{
Type t = typeof(Class1);
var obj = new TestClass(t);
obj.TestMethod1();
}
}
class TestClass
{
private Type _caller;
public TestClass(Type type)
{
_caller = type;
}
public void TestMethod1()
{
TestMethod2();
}
private void TestMethod2()
{
//Do something with the class
}
}
You might check out this code to find your solution without having to pass class instances or type parameters, etc....:
class Program
{
static void Main(string[] args)
{
var c = new Class1();
c.Method1();
}
}
class Class1
{
public void Method1()
{
var obj = new TestClass();
obj.TestMethod1();
}
}
class TestClass
{
public void TestMethod1()
{
TestMethod2();
var mth = new StackTrace().GetFrame(1).GetMethod();
var clss = mth.ReflectedType.Name;
Console.WriteLine("Classname in Method1(): {0}", clss);
}
private void TestMethod2()
{
//get the calling class
var mth = new StackTrace().GetFrame(1).GetMethod();
var clss = mth.ReflectedType.Name;
Console.WriteLine("Class in .Method2(): {0}", clss);
}
}
This will get the Type that first called TestClass. It prints:
TestStack.Class1
TestStack.Program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace TestStack
{
class Class1
{
public void Method1()
{
var obj = new TestClass();
obj.TestMethod1();
}
}
class TestClass
{
public void TestMethod1()
{
TestMethod2();
}
private void TestMethod2()
{
StackTrace st = new StackTrace();
Type calling = null;
foreach (var sf in st.GetFrames())
{
var type = sf.GetMethod().DeclaringType;
if (type != this.GetType())
{
calling = type;
break;
}
}
Console.WriteLine(calling);
}
}
class Program
{
static void Main(string[] args)
{
Class1 class1 = new Class1();
class1.Method1();
TestClass testClass = new TestClass();
testClass.TestMethod1();
}
}
}