I am writing a class library(API) in C#. The class is non-static and contains several public events. Is it possible to trigger those events from a static method in a separate class?
For example...
class nonStaticDLLCLASS
{
public event Event1;
public CallStaticMethod()
{
StaticTestClass.GoStaticMethod();
}
}
class StaticTestClass
{
public static GoStaticMethod()
{
// Here I want to fire Event1 in the nonStaticDLLCLASS
// I know the following line is not correct but can I do something like that?
(nonStaticDLLCLASS)StaticTestClass.ObjectThatCalledMe.Event1();
}
}
I know you typically have to create an instance of the non-static class in order to access it's methods but in this case an instance has already been created, just not by the class that is trying to access it.
No, instance members can only be invoked/accessed on a valid instance of the type.
In order for this to work you must pass an instance of nonStaticDLLCLASS to StaticTestClass.GoStaticMethod and use that instance reference to invoke/access the non-static members.
In your example above how do you specify which instance of the type you are accessing? The static method has no knowdlege of any instance so how does it know which one to use or if there are any loaded in memory at all?
Consider this example:
using System;
class Dog
{
public String Name { get; set; }
}
class Example
{
static void Main()
{
Dog rex = new Dog { Name="Rex" };
Dog fluffy = new Dog { Name="Fluffy" };
}
static void sayHiToDog()
{
// In this static method how can I specify which dog instance
// I mean to access without a valid instance? It is impossible since
// the static method knows nothing about the instances that have been
// created in the static method above.
}
static void sayHiToDog(Dog dog)
{
// Now this method would work since I now have an instance of the
// Dog type that I can say hi to.
Console.WriteLine("Hello, " + dog.Name);
}
}
Instance methods can only be called on instances. In your example, the instance is calling the static method. Can you give the static method a parameter allowing the instance to pass in a reference to itself? Something like this:
class nonStaticDLLCLASS
{
public event Event1;
public CallStaticMethod()
{
StaticTestClass.GoStaticMethod(this);
}
}
class StaticTestClass
{
public static GoStaticMethod(nonStaticDLLCLASS instance)
{
// Here I want to fire Event1 in the nonStaticDLLCLASS
// I know the following line is not correct but can I do something like that?
instance.Event1();
}
}
I think you need to clarify your question to specify why you can't do something like this, or why the instance can't raise its own event.
Related
Someone once wrote:
The space required for an instance depends only on the fields.
The methods require memory too but only one time per class. Like static fields. That memory is allocated when the class is loaded.
But what happens if a class with say like 5 methods and no fields get multiple instances in fields of other classes(composition).
Do they require more memory? Or would it be the same as static methods?
I do ask this question also because maybe it even gets optimised when compiling?
Is there a differents to static class with static methods? Other than u need to create the class each time or pass it around?
Eg.:
class Test1
{
public void DoThis()
{
...
}
public void DoThat()
{
...
}
}
class Test2
{
public void DoSomething()
{
...
}
private Test1 sample = new Test1();
}
class Test3
{
public void DoSomethingElse()
{
...
}
private Test1 sample = new Test1();
}
And so on...
"Behind the scenes", a class method is just like a static method, with the class instance beeing passes by reference as the first parameter.
That is, unless you use virtual methds, which "behind the scenes" are saved as instance members.
That is, because as long as you don't override a method, there is simply no reason to waste an instance's space.
Therefore, the size of both your class instances won't be affected by any non-virtual method you add to the class.
This concept can change between programming languages tho. For example, in Java and Python class methods are virtual by default.
I have a bunch of static classes I would like to access easily by adding them all to a List.
Is there a way to add these static classes to a list? I get a "This type is used like a variable" error.
public static class PCM1_Setup : IGUI_to_BFC
{
//PCM1_FORMAT
public static void Setup_toBFC()
{
//uses the checkboxes to update the BFC
//Determine the value to write to the field based on the check boxes
RegmapInputReader.BitField BF;
GB.BFC.name_to_BitField_Dict.TryGetValue("PCM1_FORMAT", out BF);
}
public static void Setup_fromBFC()
{
//Sets up the check boxes from the BFC
}
}
public static class PC2
{
List<IGUI_to_BFC> abe = new List<IGUI_to_BFC>();
PC2()
{
abe.Add(PCM1_Setup); //ERROR HERE----------------------
}
}
You can't pass a type as a method parameter. Making the PCM1_Setup class non-static and all its methods instance methods (without the static modifier) and passing a new instance of the class as the parameter for abe.Add will solve the problem.
Alternatively, you can make abe of type List<Type> and use the typeof operator to add a reference to the type of the PCM1_Setup class.
List<Type> abe = new List<Type>();
PC2()
{
abe.Add(typeof(PCM1_Setup));
}
Then you can call any of its methods using the Type.GetMethod function (that's reflection):
foreach (Type T in abe)
{
if (T == typeof(PCM1_Setup))
{
T.GetMethod("Setup_toBFC").Invoke(null, null);
}
}
Keep in mind the example above it's not the best option and you'd be better off using the first one.
You are using a static class. So you never have instance of it that can be added to the list. If you want to have a single instance and access it without creating a new instance every time you need it you can implement some form of a singleton. Then you can add the instance of the singleton to the list.
public class PCM1_Setup : IGUI_to_BFC
{
private static PCM1_Setup instance;
public static PCM1_Setup Instance
{
get
{
if (instance == null)
{
instance = new PCM1_Setup();
}
return instance;
}
}
private PCM1_Setup()
{
}
...
}
PCM1_Setup class is no longer static. The method should also be implemented as instance methods.
Then you add a singleton instance to the list from your example:
public static class PC2
{
static List<IGUI_to_BFC> abe = new List<IGUI_to_BFC>();
static PC2()
{
abe.Add(PCM1_Setup.Instance);
}
}
Note that the constructor of the PC2 class has to be static as well since the class is static.
One issue with implementing the list of IGUI_to_BFC type is that when accessing items from the list you have to cast the instance to the child class type:
((PCM1_Setup)abe[0]).Setup_fromBFC();
I got 2 windows that are not parents/children of each other and classes made for each once. Let's name them ClassA and ClassB. I am rising an event clicking button in ClassA. All i want to do is to pass variable from Class B after that button click and after that make one of ClassA functions to execute using that variable.
It can be done without additional events by having an instance of the ClassB. You obviously need that instance unless it's a static class. You can pass the instance, for example, in a constructor or using a property.
public ClassA
{
private ClassB classBInstance;
public ClassA(ClassB classBInstance)
{
this.classBInstance = classBInstance;
}
void buttonClick(...)
{
classBInstance.SomeFunction(someVariable);
}
}
public ClassB
{
void SomeFunction(paramater)
{
mySecretVariable = parameter;
CallAnotherMethodThatUsesThisVariable();
}
}
I have a job interview tomorrow and I'm trying to answer this question:
There is a class named C and method m in this class, this class have also empty constructor:
Main ()
{
C c = new c();
}
Class C {
public c {
//empty constructor
}
public m {
//does something - doesnt mind
}
}
And what you have to do is to change the code so that in a creation of an instance class C, the method m would be called before the class constructor.
You have to do this without changing the main (edit only the class code).
Thanks in advance!
Like the other answers have said, you can make the method static. But then you need to explicitly call it. If you make a static class constructor, that will get called once automatically (you don't need to call it), the first time the class is referenced (like when you construct the first instance). You can't exactly control when it executes, but it will execute before the first instance is constructed. Based on the way they've worded the question (you can't change the Main method), I think static class constructor is the answer they're looking for.
http://msdn.microsoft.com/en-us/library/k9x6w0hc%28v=vs.80%29.aspx
Static constructors have the following properties:
A static constructor does not take access modifiers or have parameters.
A static constructor is called automatically to initialize the class before the first instance is created or any static members are
referenced.
A static constructor cannot be called directly.
The user has no control on when the static constructor is executed in the program.
Java doesn't have static class constructors, but they do have static initialization blocks..
static {
// code in here
}
To call a class's method before its constructor gets called you either have to turn this method into static so you don't need an instance of that class to call it, or (in C#) you can use FormatterServices.GetUninitializedObject Method to get an instance of your class without running the constructor (which of course may not be a wise thing to do).
In JAVA:
make method static and call your method in static block.
class C{
static{
m();
}
public C() {
System.out.println("Constructor Called..");
}
public static void m() {
System.out.println("m() is called.");
}
}
Main call
public static void main(String[] args) {
new C();
}
In both Java and C# you can use, base class constructors, static constructors (Edit: static initializer block in Java), and field initializers, to call code before the C class's constructor executes without modifying Main.
An example using a field initializer block in Java:
class C {
{ m(); }
public C() {
System.out.println("cons");
}
public void m() {
System.out.println("m");
}
}
This prints "m", then "cons". Note that m is called every time a C is constructed. A static initializer block would only be called once for the JVM.
Its basic OOP. You have to make a public static method and call it. That method can then call the constructor, or you can call the constructor directly from main.
Before you call the constructor, the object don't exist, therefore no instance methods exist, therefore nothing tied to the instance/object can be called. The only things that do exist before the constructor is called is the static methods.
Following way seems to achieve what is required. Without using static methods/variables
namespace FnCallBeforeConstructor
{
static void Main(string[] args)
{
MyClass s = new MyClass();
Console.ReadKey();
}
partial class MyClass: Master
{
public override void Func()
{
Console.WriteLine("I am a function");
}
public MyClass()
: base()
{
Console.WriteLine("I am a constructor");
}
}
class Master
{
public virtual void Func() { Console.WriteLine("Not called"); }
public Master()
{
Func();
}
}
}
Output is:
I am a function
I am a constructor
I am trying to use a method inside class, from another class.
namespace Crystal.Utilities
{
public class Logging
{
public static void Log()
{
//dostuff
Crystal.MainForm.general_log_add_item("Hello World");
}
}
}
namespace Crystal
{
public partial class MainForm : Form
{
public void general_log_add_item(string msg)
{
listBox1.Items.Add(msg);
}
}
}
I want to be able to call Crystal.Utilities.Logging.Log() from anywhere, and that to be able to call Crystal.MainForm.general_log_add_item() . But It doesn't let me, because if I put it as public, then I can't see it, if it's static then It can't interact with my listbox.
This is a wrong approach. Your class should not call into the UI, as the UI could change. The class should not know nor care about the UI. Instead, the class could expose an event that the form could subscribe to, and update based upon the information contained within the event's arguments.
Here's a hastily thrown together example.
class Program
{
static void Main()
{
Logger.OnLogging += Logger_OnLogging;
Logger.Log();
Logger.OnLogging -= Logger_OnLogging;
}
static void Logger_OnLogging(LoggingEventArgs e)
{
Trace.WriteLine(e.Message);
}
}
public class Logger
{
public delegate void LoggingEventHandler(LoggingEventArgs e);
public static event LoggingEventHandler OnLogging;
public static void Log()
{
// do stuff
RaiseLoggingEvent("Data logged");
}
protected static void RaiseLoggingEvent(string message)
{
if (OnLogging != null)
OnLogging(new LoggingEventArgs(message));
}
}
public class LoggingEventArgs : EventArgs
{
public LoggingEventArgs(string message)
{
this.Message = message;
}
public string Message { get; private set; }
}
Instead of implementing it as a static method, try implementing as a singleton. It's a common trick to make an instance global in scope, and restrict to one instance, without making everything static (and thus unable to be used as an instance).
You have to understand that the window is not static, there is one instance of him, thats why the method cant be static,
you can use
Application.Windows to reach this instance and call the add method.
or you can register the window in his constructor on another class that will mediate the Logging and the window.
If you don't understand tell me and I'll try to be more clear
When you declare a method as "static" you're saying that it's not dependent upon a specific instance of the class it's in.
For example if you have a class named "chair" and you want to count how many chairs there are, you'll do that with a static field, and a static method to return that field's value.
The count of all chairs is not related to a specific chair.
In your case you want to add a static method to add an item to a specific instance of a Form. That's impossible and doesn't make sense.
If you want to add an item to a listBox, it must be through a public method.
So basically what I'm saying is - rethink what you're trying to do, there's a good explanation as to why you're not succeeding in doing that.