creating a new object triggers an exception c# - c#

When I create a new thing from the MyClass class it triggers an exception.
namespace class_test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
MyClass thing = new MyClass();
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = thing.x.ToString();
thing.x++;
}
}
code for the class:
namespace debugging_class
{
class MyClass : Form1
{
public int x = 100;
}
}
By testing I found out that the : Form1 from the class code is the issue. I am using that because I want to access Form1 objects in the class. Is there any way to do that without using : Form1?

The problem is indeed one of infinite recursion. When you create a MyClass object, it calls the constructor for that class. Because MyClass inherits from Form1 and you haven't specified a default (parameterless) constructor for MyClass, it will implicitly call the constructor for Form1.
The problem is that you have in your code for Form1 a class-level variable with a default value. When a class has a field with a default value, those variables will be implicitly set with the given value at the beginning of that object's constructor. So, for example, the code:
public class SomeClass
{
public int i = 5;
public SomeClass()
{
// Just a simple call and that's it
Console.WriteLine(i);
}
}
Will actually compile to something resembling the following:
public class SomeClass
{
public int i;
public SomeClass()
{
// Assign default values to class instance fields
i = 5;
// Execute the rest of the constructor code
Console.WriteLine(i);
}
}
So here is the problem - your Form1 class has a MyClass field with a default value of new MyClass(). That field will be assigned in Form1's constructor. Because MyClass inherits from Form1, then Form1's constructor will also get called, which will then create a new instance of MyClass, which will call the constructor for Form1 again... You see how this turns into infinite recursion? The constructors of Form1 and MyClass are calling each other back and forth forever and ever (or at least until the program reaches the limit of recursion and throws a StackOverflowException).
The reason that your code runs fine if you remove the default value and instead put the instantiation of the field inside a separate method is because that method won't get called until later in your program. MyClass's constructor will call Form1's constructor and then return, allowing your program to continue on its merry way.

Related

How to declare c# constructor with Action<T> argument (like passing a pointer to func in C) [duplicate]

This question already has answers here:
A field initializer cannot reference the nonstatic field, method, or property
(6 answers)
Closed 1 year ago.
I have a class like this
class Class1
{
public Class1(Action<string> Log)
{
Log("bla bla"); // to be output by project Log system
}
}
And in the main Form project I try to pass my Log function to Class1 so inside it, I can have the same log function
public partial class Form1 : Form
{
Class1 MyClass = new Class1(Log); // ERROR !
public Form1()
{
InitializeComponent();
}
public void Log(string line)
{
rtb.Text += line + "\n";
}
...
...
}
But I got this error
Error CS0236 A field initializer cannot reference the non-static field, method, or property 'Form1.Log(string)'
I just need to pass Log() function pointer to other class via it's constructor, like in C I would use a function pointer to pass as argument.
If I understood right, Action is just a shortcut for a "delegate" that always return void and can have some arguments. Compiler should know that Log() exists (and so, have a address) so why I cannot pass it as argument?
Then, how can I do that in C#?
You need to move the declaration into the constructor. Like this:
public partial class Form1 : Form
{
private Class1 MyClass;
public Form1()
{
InitializeComponent();
MyClass = new Class1(Log);
}
void InitializeComponent()
{
throw new NotImplementedException();
}
public void Log(string line)
{
}
}
There is an order in which parts of a class become available for initialization. Fields get declared before the constructor runs, then the constructor runs. Before the constructor runs the fields can't reference any other instance field or method on the class.

Static referenced in another .cs file

I am overlooking something simple I think. I have a form with a checkbox. I need to know if the checkbox is checked in a different cs file/class to know whether to make a column header Option1 or Option2.
Form1 (Public partial class) code:
public bool Checked
{
get
{
return checkBox1.Checked;
}
}
In my Export1 class I have private void CreateCell1 that takes in the data to be exported (creating an excel file from a datatable). The section of code I can't get to work is:
if (Form1.Checked.Equals("true"))
{
newRow["Option1"] = date2;
}
else
{
newRow["Option2"] = date2;
}
I am getting -Error 1 An object reference is required for the non-static field, method, or property 'Matrix1.Form1.Checked.get'
What did I overlook?
Well, the problem here is exactly what the compiler is telling you. You need an object reference in order to access the property.
Allow me to explain.
In C#, by default, class members (fields, methods, properties, etc) are instance members. This means that they are tied to the instance of the class they are a part of. This enables behavior like the following:
public class Dog
{
public int Age { get; set; }
}
public class Program
{
public static void Main()
{
var dog1 = new Dog { Age: 3 };
var dog2 = new Dog { Age: 5 };
}
}
The two instances of Dog both have the property Age, however the value is tied to that instance of Dog, meaning that they can be different for each one.
In C#, as with a lot of other languages, there are things called static members of classes. When a class member is declared static, then that member is no longer tied to an instance of the class it is a part of. This means that I can do something like the following:
public class Foo
{
public static string bar = "bar";
}
public class Program
{
public static void Main()
{
Console.WriteLine(Foo.bar);
}
}
The bar field of the Foo class is declared static. This means that it is the same for all instances of Foo. In fact, we don't even have to initialize a new instance of Foo to access it.
The problem you are facing here is that, while Form1 is not a static class and Checked is not a static property, you are treating it as such. In order for what you are trying to do to work, you need to create an instance of Form1 and access that instance's Checked property.
Depending on how your program is structured, there are many ways of doing this. If Form1 is created in the scope where you are trying to access Checked, then this will be straightforward. If Form1 is what spawns the new scope, then common practice is to pass a reference to it in the constructor.
For example, if Form1 creates a new Form2 then we do the following:
public class Form2 : Form
{
private Form1 parent;
public Form2(Form1 parent)
{
this.parent = parent;
InitializeComponent();
}
}
And then you can access parent throughout Form2. Of course, depending on the structure of your program, the exact implementation will be different. However, the general pattern is the same. Pass the reference to Form1, from the scope it was created in, to the new class, and then access it from there.
One way or another, you need to access the specific instance of Form1 that you're trying to check.
A few ways to do this are:
Pass the instance to the class constructor
Setting a public property of the other class to the instance of the form
Pass the instance to the method directly
For example:
public class SomeOtherClass
{
// One option is to have a public property that can be set
public Form1 FormInstance { get; set; }
// Another option is to have it set in a constructor
public SomeOtherClass(Form1 form1)
{
this.FormInstance = form1;
}
// A third option would be to pass it directly to the method
public void AMethodThatChecksForm1(Form1 form1)
{
if (form1 != null && form1.Checked)
{
// Do something if the checkbox is checked
}
}
// This method uses the local instance of the Form1
// that was either set directly or from the constructor
public void AMethodThatChecksForm1()
{
AMethodThatChecksForm1(this.FormInstance);
}
}
This class would need to be instantiated by the instance form1 using one of these methods:
// Pass the instance through the constructor
var someOtherClass = new SomeOtherClass(this);
// Or set the value of a property to this instance
someOtherClass.FormInstance = this;
// Or pass this instance to a method of the class
someOtherClass.AMethodThatChecksForm1(this);

How to access a visual component from another form in c#

I have a textbox in my main form.
Now I have created a function which is used to set the value of the text box.
public void SetTextOfTextBox(String text)
{
textbox1.text = text;
}
Now in my main form I call another class (class b) which does some work for me. Now i want to be able to call my setTextofTextBox function from class b.
Now if I try Form1.SetTextOfTextBox("test"); this doesn't work.
What am I doing wrong?
How do I access components of a a Form from another class.
Form1.SetTextOfTextBox("test"); this doesn't work
This doesn't work because SetTextOfTextBox is not static and you cannot access a non-static function directly. And you can't make it static either because your textbox is form level control.
How do I access components of a a Form from another class
You will have to pass the instance of Form1 to your other class to access it. Something like
Class B = new ClassB(this); //where this is the instance of Form1.
You will need a reference to the instance of Form1 in class b, otherwise you cannot call member methods.
Something like this:
class Form1 : System.Windows.Forms.Form {
void functionInForm1() {
ClassB objB = new ClassB();
objB.doSomething(this);
}
}
class ClassB {
void doSomething(Form1 form) {
form.SetTextOfTextBox("test");
}
}
Find out the Form1 and call the method:
foreach (var form in Application.OpenForms) {
Form1 myForm = form as Form1;
if (!Object.ReferenceEquals(null, myForm)) {
myForm.SetTextOfTextBox("Test");
break;
}
}
Did u try using delegates.
Specify the delegates in your ClassB like this.
public delegate void OnDone(string textValue);
public event OnDone OnUserDone;
after completing the task in ClassB call event:
OnUserDone("DoneClassB");
When u create the object of class in form map delegate function.
Classb b=new Classb();
b.OnUserDone += new Classb.OnUsrControlDone(CompletedClasss);
Define the function in form like below.
void CompletedClasss(string textValue)
{
SetTextOfTextBox( textValue);
}

Error 1 A field initializer cannot reference the non-static field, method, or property

public partial class Form1 : Form
{
Class1 class = new Class1(30,a);
public Form1()
{
InitializeComponent();
}
public int a = 0;
private void Timer1_Tick(object sender, EventArgs e)
{
a += 1;
}
}
I want to use the variable 'a' in my calss but i cant get "move" it over to my class via the constructor i'm using.
The error message i recive is :
Error: A field initializer cannot reference the non-static field, method, or property.
I know it's a basic problem but help is appreciated
class Class1
{
private int r;
private int x;
public Construct(int p, int c)
{
this.r = p;
this.x = c;
}
}
Just move the initialization of class1 into a constructor:
class Form1 {
int a = 0;
Class1 obj1;
public Form1() {
obj1 = new Class1(a);
}
}
You cannot initialize a field that depends on another field of the class.
From the C# Language Specification 10.5.5:
Field declarations may include variable-initializers. For static
fields, variable initializers correspond to assignment statements that
are executed during class initialization. For instance fields,
variable initializers correspond to assignment statements that are
executed when an instance of the class is created.
and
The default value initialization described in ยง10.5.4 occurs for all
fields, including fields that have variable initializers. Thus, when a
class is initialized, all static fields in that class are first
initialized to their default values, and then the static field
initializers are executed in textual order. Likewise, when an instance
of a class is created, all instance fields in that instance are first
initialized to their default values, and then the instance field
initializers are executed in textual order.
So, in your code, a isn't initialized before class, although I don't think the compiler cares whether is comes before or after alphabetically. It just doesn't allow you to use one instance variable to initialize another.

An object reference is required for the non-static field, method or property error

I am developing a C# windows form application and on the main form I have a TabControl. It is declared in the Form1.Designer.cs file as follows:
public System.Windows.Forms.TabControl logFileCollectorTabControl;
In another class file in my project I want to use this TabControl as follows:
logFileCollectorForm.logFileCollectorTabControl.TabPages.Add(newTabPage);
But I get the error 'An object reference is required for the non-static field, method or property error'. So my question is, there must be an object of the Form class declared somewhere because the form launches when I launch the application, so how do I find out what that is, or how can I solve this issue, any help is greatly appreciated!
This is usually overcome by passing in an instance of Form1 to the constructor of the calling class, then keeping it in a field until needed.
//somewhere in Form1
OtherClass other = new OtherClass (this);
// OtherClass.cs
class OtherClass {
Form1 _opener;
public OtherClass(Form1 opener) {
_opener = opener;
}
}
Is your other class aware of logFileCollectorForm?
If you do not pass a reference to the form to the other class, then the other class does not know what Is logFileCollectorForm is referencing.
//example of another class
class AnotherClass
{
Form1 logFileCollectorForm;
public AnotherClass(Form1 logFileCollectorForm)
{
this.logFileCollectorForm = logFileCollectorForm;
}
public DoSomething(String newTabPage)
{
logFileCollectorForm.logFileCollectorTabControl.TabPages.Add(newTabPage);
}
}
There is probably no need to pass an instance of an entire form, you could pass a reference to your TabControl only. But it's still bad design in my opinion. Your logic should be separated from UI. If your class performs some computations, database operations or what not, it shouldn't really have to "know" about your window at all, because this is inflexible. Implement an event instead.
Another option is to keep a static reference to the main form in the Program class.
static class Program
{
internal static Form1 MainForm { get; set; }
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MainForm = new Form1();
Application.Run(MainForm);
}
}
class OtherClass
{
public void AddNewTab(TabPage newTabPage)
{
Program.MainForm.logFileCollectorTabControl.TabPages.Add(newTabPage);
}
}

Categories

Resources