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();
}
Related
Here is the code I currently have, the question follows after:
class Program
{
static void Main(string[] args)
{
var obj1 = new A();
obj1.DoIt();
obj1.SetFlyBehavior(new BehaviorB());
obj1.DoIt();
string input = Console.ReadLine();
}
};
class BaseOfA
{
protected ObjectBehavior behavior;
public void DoIt()
{
behavior.DoIt();
}
public void SetBehavior(ObjectBehavior ob) {
behavior = ob;
}
};
class A : BaseOfA {
public A() {
behavior = new BehaviorA();
}
}
interface ObjectBehavior {
void DoIt();
}
class BehaviorA : ObjectBehavior {
void ObjectBehavior.DoIt() {
Console.WriteLine("Behavior: A");
}
}
class BehaviorB : ObjectBehavior {
void ObjectBehavior.DoIt() {
Console.WriteLine("Behavior: B");
}
}
Now my question is, in this case, how am I going to make it work so that I can assign both BehaviorA and BehaviorB to instance obj1 as long as they implement ObjectBehavior?
You are calling obj.SetFlyBehaviour this method is not defined anywhere. The method you define on BaseOfA is called SetBehaviour. Once that is fixed the code you gave compiles fine for me
The follow code does not compile:
public class Test
{
public void Run()
{
List<MyClass<dynamic>> listOfMyClasses = new List<MyClass<dynamic>>();
MyClass<dynamic> myClass = new MyClass<int>(); // Error here
listOfMyClasses.Add(myClass);
}
public class MyClass<T>
{
public void DoSomething() { }
public void DoSomethingSpecial<T>(T t) { }
}
}
However, I believe it makes sense logically (please let me know if I'm mistaken). Presumably it is useful, for I can call DoSomething without knowing the type parameter. How can I accomplish the addition of myClass to the list?
Instead of using a list of MyClass<dynamic> just use a List of dynamic:
public void Run()
{
List<dynamic> listOfMyClasses = new List<dynamic>();
dynamic myClass = new MyClass<int>();
listOfMyClasses.Add(myClass);
}
public class MyClass<T>
{
public void DoSomething() { }
}
Is using a switch on object types really the main way of calling a common function of stored references to class objects? It doesn't have to be a 'object' value type.
using System;
public class MainClass { public void Main() { print "hello world"; } }
public class SubClassOne : MainClass { }
public class SubClassTwo : MainClass { }
public class Storer
{
public void Main() {
object[] objects = new object[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
for(i=0;i<2;i++)
{
switch(objects[i].GetType().ToString())
{
case: "SubClassOne":
SubClassOne subclass = objects[i];
subclass.Main();
break;
case: "SubClassTwo":
SubClassTwo subclass = objects[i];
subclass.Main(); //Could probably call after the switch
break;
}
}
}
}
Note: Code not parsed, so there may be serious errors.
"Stringly" typed object oriented code is such a bad idea. You (almost) never need to know the type of an object via a string.
Changing your "print" to Console.WriteLine and main to this works fine
MainClass[] stuff = new MainClass[2];
stuff[0] = new SubClassOne();
stuff[1] = new SubClassTwo();
foreach(var item in stuff)
{
item.Main();
}
If the problem is you are determined to use an array of object, AlexH has answered.
In that case, I suggest to use as keyword to perform a safe cast operation :
using System;
public class MainClass { public void Main() { print "hello world"; } }
public class SubClassOne : MainClass { }
public class SubClassTwo : MainClass { }
public class Storer
{
public void Main() {
object[] objects = new object[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
for(i=0;i<2;i++)
{
var myMainClass = objects[i] as MainClass;
if (myMainClass != null)
{
myMainClass.Main();
}
}
}
}
As wudzik said it should be even better to declare objects as a MainClass array
There are many ways of solving this in a nice way, depends on:
If you know types and there are not too much of them:
Use LINQ OfType<>(). For more details see MSDN
foreach (var item in objects.OfType<SubClassOne>())
{
item.Main();
}
foreach (var item in objects.OfType<SubClassTwo>())
{
item.Main();
}
If there are many types, just introduce common interface
interface ISharedApi
{
void Main();
}
class SubClassOne : ISharedApi
class SubClassTwo : ISharedApi
And implement this/mark each type by it, then you just need single loop:
var objects = new List<ISharedApi>();
objects.Add(new SubClassOne());
objects.Add(new SubClassTwo());
foreach (var item in objects)
{
item.Main();
}
You should implement a more object oriented solution. Instead of creating an array consisting of objects you should make MainClass abstract and define an abstract method Main. After that you should implement Main in you sublclasses.
In this way you can exchange your code to:
using System;
public abstract class MainClass { public abstract void Main(); }
public class SubClassOne : MainClass {
public override void Main() { print "SubClassOne, hello world"; }
}
public class SubClassTwo : MainClass {
public override void Main() { print "SubClassTwo, hello world"; }
}
public class Storer
{
public void Main() {
MainClass[] objects = new MainClass[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
foreach(MainClass mc in objects)
{
mc.Main();
}
}
}
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();
}
}
}
The code below throws an exception because the abstract constructor is called before the child constructor.
I need to provide an abstract class to capsule some logic from a different part of the program. However i also need to check if the abstract members are initialised correctly rigth after creation without the childclass having any influence over this.
the compiling example below should illustrate my question.
using System;
namespace Stackoverflow
{
class Program
{
static void Main(string[] args)
{
var x = new Thing(5);
var y = new Child(x);
}
}
class Child : AbstractParent
{
Thing childthing;
public Child(Thing provided) : base(){
childthing = provided;
}
public override void Initialise(){
//Exception is thrown here - childthing is still null
parentthing = childthing.Add(1);
}
}
abstract class AbstractParent
{
protected Thing parentthing;
public AbstractParent(){
Initialise();
AssertThingyNotNull();
}
private void AssertThingyNotNull(){
if (parentthing == null) throw new Exception("Waaa");
}
public abstract void Initialise();
}
class Thing
{
private int i;
public Thing(int i){
this.i = i;
}
public Thing Add(int b){
i += b;
return new Thing(i);
}
}
}
Edit #1:
Is there some way to do this by reflecting into the caller (should be the creator of child rigth?) and then reacting on the end of that call?
Edit #2:
Getting the .ctor that creates the child is easy. Manipulating the methods seems something between impossible and a bad idea.
foreach (StackFrame frame in new StackTrace().GetFrames())
{
Console.WriteLine(frame.GetMethod().Name);
}
You can't, basically. This is why you should avoid calling virtual (or abstract) members from a constructor as far as possible - you could end up with code which is running with an incomplete context. Any variable initializers are executed before the base class constructor is called, but none of the code within the constructor body is.
If you need to perform initialization and only want to do that when the derived class constructor is running, then just call Initialise from the derived class constructor to start with.
You can do something similar to what Microsoft did with InitializeComponent()
then let the children call it whenever it can.
Try this.
Edited = cleaner version.
using System;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
var x = new Thing(5);
var y = new Child(x);
}
}
class Child : AbstractParent
{
public Child(Thing provided)
: base()
{
parentthing = provided;
base.Initialise();
}
}
abstract class AbstractParent
{
protected Thing parentthing;
public AbstractParent()
{
}
private void AssertThingyNotNull()
{
if (parentthing == null) throw new Exception("Waaa");
}
public void Initialise()
{
AssertThingyNotNull();
}
}
class Thing
{
private int i;
public Thing(int i)
{
this.i = i;
}
public Thing Add(int b)
{
i += b;
return new Thing(i);
}
}
}