I have a class P as part of namespace D with several fields and related properties
namespace Driver
[Export(typeof (P))]
public class Pilot : Send
{
private bool _b1;
...
public bool B1
{
get { return _b1; }
private set
{
if (_b1 != value)
{
_b1 = value;
NotifyOfPropertyChange(() => B1);
}
}
}
And then another class in the same namespace with some methods
namespace Driver
public class PilotEng
{
public void Statistics()
{
....
}
public void Running()
{
....
}
What is the best way to access and use the parameters of class P in class PE methods?
There are many ways for PilotEng to access information from Pilot.
Pass in instance of Pilot at PilotEng construction:
public class PilotEng
{
private Pilot myPilot;
public PilotEng(Pilot pilot)
{
myPilot = pilot;
}
public void Statistics()
{
var whatever = myPilot.B1;
....
}
public void Running()
{
....
}
}
somewhere else...
public void SomeMethod()
{
Pilot p = new Pilot();
PilotEng pe = new PilotEng(p);
pe.Statistics();
}
update your method signature(s) to take in an instance of pilot to work with:
public class PilotEng
{
public void Statistics(Pilot pilot)
{
var whatever = pilot.B1;
....
}
public void Running()
{
....
}
}
somewhere else...
public void SomeMethod()
{
Pilot p = new Pilot();
PilotEng pe = new PilotEng();
pe.Statistics(p);
}
Both are valid, one may be more valid than another, and there are several other ways to accomplish this. It all depends on what you're actually trying to do.
Related
So i'm trying to organize my functions into nested classes so i can call them like: "Player.Trigger_Functions.TakeDamage()" rather than calling it as such: "Player.TakeDamage()". I suppose it is a less efficient way to call the functions the way I'm suggesting but it would help separate the functions into distinct categories while remaining on the same file.
Here is some test code but i can't get it to compile online to see if it works.
(some of the functions need to be able to interact with each-other despite being in separate containers which i think is a problem)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class Program
{
public class meme{
public int thicc = 0;
public oof nest1 = new oof();
public watermelone nest2 = new watermelone();
public class oof : meme
{
public void here(){
thicc++;
}
public void call(){
nest2.here();
System.Console.WriteLine("oof" + thicc);
}
}
public class watermelone : meme
{
public void here(){
thicc++;
}
public void call(){
nest1.here();
System.Console.WriteLine("watermelone" + thicc);
}
}
}
public static void Main(){
meme me = new meme();
me.nest1.call();//adding 1
me.nest2.call();//adding 1
System.Console.WriteLine("here is the current thicc value of the me class:" + me.thicc);
}
}
Ok yeah so this code wouldn't work at all, i didn't put that much thought into it but you get the idea of what i'm trying to accomplish.
You can use interfaces to break up the functionality of your class into related groups.
From this:
class Person
{
void sayHello() { }
void sayGoodbye() { }
void walkForward() { }
void walkBackward() { }
}
Refactor into this:
interface ISpeak
{
void sayHello();
void sayGoodbye();
}
interface IWalk
{
void walkForward();
void walkBackward();
}
class Person : ISpeak, IWalk
{
void ISpeak.sayHello() { }
void ISpeak.sayGoodbye() { }
void IWalk.walkForward() { }
void IWalk.walkBackward() { }
}
class Program
{
static void Main(string[] args)
{
Person person = new Person();
IWalk walk = person;
ISpeak speak = person;
speak.sayHello();
walk.walkForward();
}
}
I'm using IoC to define some behavior in my inherited class. I have a property
protected virtual bool UsesThing { get { return true; } }
in my top-level class.
In my inherited class I have
protected override bool UsesThing { get { return false; } }
I'm using the property in my top level class, and it's using the top-level value. Is there a way to make it use the inherited value? I thought that's what virtual was supposed to do.
Code Example:
using System;
public class Program
{
public static void Main()
{
B b = new B();
b.PrintThing();
//I want this to print the value for B
}
public class A
{
protected virtual bool Enabled
{
get
{
return true;
}
}
public void PrintThing()
{
Console.WriteLine(this.Enabled.ToString());
}
}
public class B : A
{
protected override bool Enabled
{
get
{
return false;
}
}
}
}
Here's a Dot Net Fiddle demonstrating my problem
You could do something like this:
https://dotnetfiddle.net/SOiLni
A in of itself knows nothing of B's implementation, so you have to instantiate an object of B in order to access its overriden property.
Slightly modified version of your fiddle:
public class Program
{
public static void Main()
{
A a = new A();
a.PrintThing();
A newA = new B();
newA.PrintThing();
}
public class A
{
protected virtual bool Enabled
{
get
{
return true;
}
}
public void PrintThing()
{
Console.WriteLine(this.Enabled.ToString());
}
}
public class B : A
{
protected override bool Enabled
{
get
{
return false;
}
}
}
}
Given your code example, A's Enabled will be printed, as it should.
When you create an A it knows nothing about B, so polymorphically, you can't expect it to use its value. This makes since, because if you had a class C that also derived from A, it wouldn't know what to use!
On the other hand, if you had written:
public static void Main()
{
A a = new B();
a.PrintThing();
}
You would expect (correctly) that it would use B's override, as you created an instance of that type.
You must have some other issue with your code. This code will print 'true' and 'false' respectively:
public class BaseClass {
public virtual bool DoesSomething {
get {
return true;
}
}
public void Print() {
Console.WriteLine(DoesSomething);
}
}
public class ChildClass : BaseClass {
public override bool DoesSomething {
get {
return false;
}
}
}
Then using these classes:
BaseClass bc = new BaseClass();
bc.Print();
ChildClass sc = new ChildClass();
sc.Print();
If I was to guess you are probably creating instances of the parent class even though your intention is to create instances of the child class.
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();
}
}
}
I am trying to make a class so when I do the following inside a file:
Functions LoginFunctions = new Functions();
LoginFunctions.loadFunctions();
It will create my object which I need, and make it public so every form which calls the class will be able to use it. The class file is below.
namespace App
{
public class Functions
{
public void loadFunctions()
{
TaskbarItemInfo taskbarItemInfo = new TaskbarItemInfo();
}
}
}
It doesn't seem to be making the taskbarItemInfo object public, and it is not letting me use it anywhere else other then inside the class. How do I make it public so every file that calls the class can use the object?
As the others have mentioned, make it a property, for example like so:
public class Functions
{
public TaskbarItemInfo TaskbarItemInfo { get; private set; }
public void loadFunctions()
{
this.TaskbarItemInfo = new TaskbarItemInfo();
}
}
Your taskbaritem class is in the scope of the method and therefore you wont be able to access it outsite of the class.
Create a public property or return it in the method.
namespace App
{
public class Functions
{
private TaskbarItemInfo _taskbarItemInfo;
public TaskbarItemInfo taskbarItemInfo
{
get
{
return _taskbarItemInfo;
}
}
public void loadFunctions()
{
_taskbarItemInfo = new TaskbarItemInfo();
}
}
}
I would also go and change the loadFunctions method to a constructor which creates all the objects you need.
public Functions()
{
_taskbarItemInfo = new TaskbarItemInfo();
}
In the example you provide, taskbarItemInfo is declared within the local scope of the loadFunctions() method. If you want it to be public for some class, you must make it a class member before you can make it public.
You need to make the variable public.
namespace App
{
public class Functions
{
public TaskbarItemInfo TaskbarItemInfo { get; private set; }
public void loadFunctions()
{
TaskbarItemInfo = new TaskbarItemInfo();
}
}
}
EDIT: You could also do the initialization of the items in the constructor.
namespace App
{
public class Functions
{
public TaskbarItemInfo TaskbarItemInfo { get; private set; }
public Functions()
{
loadFunctions();
}
private void loadFunctions()
{
TaskbarItemInfo = new TaskbarItemInfo();
}
}
}
Then you don't need the LoginFunctions.loadFunctions(); line of code after you initialize your LoginFunctions object.
You probably want to access it as a property which generates a private static member when needed.
namespace App
{
public class Functions
{
private static TaskbarItemInfo _taskbarItemInfo;
public static TaskbarItemInfo TaskBarItemInfoProperty
{
get{
if (_taskbarItemInfo == null)
{
_taskbarItemInfo = new TaskbarItemInfo();
}
return _taskbarItemInfo;
}
}
}
public class Test
{
public void testFunction()
{
Functions.TaskBarItemInfoProperty.doSomething();
}
}
}