I know from the title you would say it's a duplicate, but...
So, I have created my class and made some objects (of class Masina) in MainWindow class constructor:
public class MainWindow
{ // example
private Masina[] _masina = new Masina[10];
_masina[0].Load(1, 'x'); // works
SomeFunction(_masina);
}
When I use this class functions in Constructor it works fine, but when I try to use some function and pass this argue like this:
public static void SomeFunction(Masina[] masina)
{
for (int i = 0; i < 10; i++)
try
{
masina[i].Load(i, 'x');
}
catch
{
}
}
then SomeFunction takes this argue as not referenced. ref don't work for me!
Can anyone help me to solve ?
Probably you want to initialize the Masina[] array in the constructor, like this:
public class MainWindow {
// Declaraion is OK, calling method _masina[0].Load(1, 'x') - is not
private Masina[] _masina = new Masina[10];
// constructor is the place you're supposed to put complex initialization to
public MainWindow() {
// You can call the method in the constructor
SomeFunction(_masina);
}
public static void SomeFunction(Masina[] masina) {
// validate arguments in the public methods
if (null == masina)
throw new ArgumentNullException("masina");
// do not use magic numbers (10), but actual parameters (masina.Length)
for (int i = 0; i < masina.Length; ++i)
masina[i].Load(i, 'x');
// hiding all exceptions - catch {} - is very bad idea
}
}
Related
I am learning about writing constructors and properties in c# and was asked to write a console app and class to operate a beverage machine. I wrote part of the class code but ran into an issue. One of the many blocks of code asks for a constructor method that starts the SodaCanCount at 5 bottles and sets the CustBalance field to zero. I don't know what this constructor should look like. I am specifically talking about the private sodaVandorClass(), right under the two private fields.
I wrote what I could so far and I have no errors however the SodaVendorClass does not look right.
namespace VendorClass
{
public class SodaVendorClass
{
// members
// fields
//Customer balance is $0 until the customer inserts a dollar
//All customer entries are one dollar increments and a soda costs one dollar.
private int CustBalance = 0;
//a machine holds 10 cans of soda
private int SodaCanCount = 5;
//A soda costs 1 dollar
//private int sodaCost = 1;
public int _SodaCanCount
{
get
{
return SodaCanCount;
}
}
public int _CustBalance
{
get
{
return CustBalance;
}
}
public int BuySoda(int pCustBalance, int SodaCanCount)
{
return SodaCanCount;
}
public void AcceptCash(int CustBalance)
{
CustBalance++;
}
public int GiveRefund(int pCustBalance)
{
return CustBalance;
}
}
I only want to see an example of a constructor that sets default values for my private class fields. Any help will be appreciated.
You can define a public constructor like below but probably you don't need one if you enable your properties to set values too
public SodaVendorClass()
{
this.CustBalance = 0;
this.SodaCanCount = 0;
}
You can make your properties writable too. Notice below are auto properties and in such case you don't need those private backing fields explicitly.
public int SodaCanCount
{
get; set;
}
public int CustBalance
{
get; set;
}
You can instantiate your type saying (using Object Initializer construct)
SodaVendorClass sc = new SodaVendorClass
{
SodaCanCount = 10,
CustBalance = 500,
};
A constructor for this class could look like this:
public SodaVendorClass () {
}
That would be an empty constructor that does nothing.
To set the two values you want, you can add some paramters:
public SodaVendorClass (int customerBalance, int sodaCount) {
this.CustBalance = customerBalance;
this.SodaCanCount = sodaCount;
}
To create an instance of this class with 5 soda cans and a customer balance of 0, you would call the constructor in the code like this:
var vendor = new SodaVendorClass(0, 5);
namespace VendorClass
{
public class SodaVendorClass
{
private int CustBalance;
private int SodaCanCount;
//...
public SodaVendorClass() // default constuctor
{
CustBalance = 0;
SodaCanCount = 5;
}
//...
}
}
Default constructor is called when you are creating object like this:
SodaVendorClass obj = new SodaVendorClass();
So obj._SodaCanCount is 5 and obj._CustBalance is 0
Also you can define constructor with parameters.
public SodaVendorClass(int balance, int count)
{
CustBalance = balance;
SodaCanCount = count;
}
and create call this constructor.
SodaVendorClass obj = new SodaVendorClass(0, 5);
A constructor is being used while creating a object like "Class obj=new Calss()". If you don define a constructor in your class a default constructor will be provided implicitly.User defined Constructor usually used for initializing value for class properties. Unlike function constructor does not have any return type at all not even void. All the answers are good.
public class SodaVendorClass{
private int CustBalance = 0;
//a machine holds 10 cans of soda
private int SodaCanCount = 5;
//A soda costs 1 dollar
//private int sodaCost = 1;
public int _SodaCanCount
{
get
{
return SodaCanCount;
}
}
public int _CustBalance
{
get
{
return CustBalance;
}
}
public SodaVendorClass(int cancount, int sodacost){
SodaCanCount=cancount;
sodaCost=sodacost;
}
}
//creating a object of Sodavendorclass
Sodavendorclass obj=new Sodavendorclass(0,0); //Provided value for class property
Notice that at the time of object creation, provided for Property. This is one of the way you can use constructor.
In Encapsulation get is readonly where set is write only
Why my output is 11110 when not using special member function?
code:
class practice_4
{
static void Main(string[] args)
{
example ABC = new example();
// ABC.Roll_ = 11;
Console.WriteLine(ABC.Roll_ );
Console.ReadLine();
}
}
class example
{
private int roll = 11110;
public int Roll_
{
get
{
return roll ;
}
//set{
// if (value > 10)
// { roll = value; }
// else
// { Console.WriteLine("error"); }
//}
}
//public example()
//{
// roll = 110;
//}
}
Output :
11110
but when I use special member function : public example()
class practice_4
{
static void Main(string[] args)
{
example ABC = new example();
Console.WriteLine(ABC.Roll_ );
Console.ReadLine();
}
}
class example
{
private int roll = 11110;
public int Roll_
{
get
{
return roll ;
}
}
public example()
{
roll = 110;
}
}
so It display Output:
110
and discard 11110
To Answer your question "Why my output is 11110 when not using special member function?"
The special member function in your class is the Constructor of your class, which means this is the special function that initializes/constructs your object from your class definition, rule to remember here is, constructors are called after your private variables statements and also when the constructor is finished the construction is finished, which means your class's internal state(variables) are now assigned(among other things).
However if you initialize the private variables like you are in private int roll = 11110; line, this line executes before the constructor is called. but as you are overwriting the value of roll in constructor, the value of your private variable gets overwritten.
In the example class you are calling the roll variable instead of the Roll_ property. If you were to try to set Roll_ instead you would get a compile time error saying something along the lines of you cannot modify a read-only property. The purpose of encapsulation is to prevent the outside world from directly modifying the value, it's not in place to prevent the class from modifying the value.
Code:
using System.IO;
using System;
using System.Reflection;
using System.Collections.Generic;
class AnyClass
{
delegate void Del(string str);
static void Main()
{
List<Del> listDel = new List<Del>();
listDel.Add(delegate(string str) { });
Console.WriteLine( listDel[0].Method.ToString() );
listDel.Add(delegate(string str) { });
Console.WriteLine( listDel[1].Method.ToString() );
for (int i = 0; i < 2; i++)
{
listDel.Add(delegate(string str) { });
}
Console.WriteLine( listDel[2].Method.ToString() );
Console.WriteLine( listDel[3].Method.ToString() );
}
}
Output:
Void m__0(System.String)
Void m__1(System.String)
Void m__2(System.String)
Void m__2(System.String)
Why do the delegates instantiated in the loop "point" to the same method (m__2) whereas the ones instantiated outside the loop point to two different methods (m__0 and m__1)?
Is there any way how to instantiate delegates that point to different/unique methods inside a loop?
Example of usage: I need to have delegates as keys in a dictionary, so they need to be unique. Instantiation inside a loop is necessary to provide enough of flexibility.
Why do the delegates instantiated in the loop "point" to the same
method (m__2) whereas the ones instantiated outside the loop point to
two different methods (m__0 and m__1)?
Because behind the scenes the compiler is caching the delegate creation. When you create the first two delegates, the compiler doesn't have knowledge that they are the same, so he creates two different cached delegates and two named methods. Inside your for loop, the compiler is optimizing by only instantiating the delegate once. He can be certain that it's the same delegate each time, instantiate it once, then cache it.
When you de-compile your code, it actually looks like this:
private delegate void Del(string str);
[CompilerGenerated]
private static Launcher.Del CS$<>9__CachedAnonymousMethodDelegate3;
[CompilerGenerated]
private static Launcher.Del CS$<>9__CachedAnonymousMethodDelegate4;
[CompilerGenerated]
private static Launcher.Del CS$<>9__CachedAnonymousMethodDelegate5;
private static void Main()
{
List<Launcher.Del> listDel = new List<Launcher.Del>();
List<Launcher.Del> arg_24_0 = listDel;
if (Launcher.CS$<>9__CachedAnonymousMethodDelegate3 == null)
{
Launcher.CS$<>9__CachedAnonymousMethodDelegate3 =
new Launcher.Del(Launcher.<Main>b__0);
}
arg_24_0.Add(Launcher.CS$<>9__CachedAnonymousMethodDelegate3);
Console.WriteLine(listDel[0].Method.ToString());
List<Launcher.Del> arg_5D_0 = listDel;
if (Launcher.CS$<>9__CachedAnonymousMethodDelegate4 == null)
{
Launcher.CS$<>9__CachedAnonymousMethodDelegate4 =
new Launcher.Del(Launcher.<Main>b__1);
}
arg_5D_0.Add(Launcher.CS$<>9__CachedAnonymousMethodDelegate4);
Console.WriteLine(listDel[1].Method.ToString());
for (int i = 0; i < 2; i++)
{
List<Launcher.Del> arg_9A_0 = listDel;
if (Launcher.CS$<>9__CachedAnonymousMethodDelegate5 == null)
{
Launcher.CS$<>9__CachedAnonymousMethodDelegate5 =
new Launcher.Del(Launcher.<Main>b__2);
}
arg_9A_0.Add(Launcher.CS$<>9__CachedAnonymousMethodDelegate5);
Console.WriteLine(listDel[2 + i].Method.ToString());
}
}
[CompilerGenerated]
private static void <Main>b__0(string str)
{
}
[CompilerGenerated]
private static void <Main>b__1(string str)
{
}
[CompilerGenerated]
private static void <Main>b__2(string str)
{
}
I would definitely not rely on a delegate being a proper key for a Dictionary.
Is there any way how to instantiate delegates that point to
different/unique methods inside a loop?
You can force the delegate to be a "fresh instance" only by explicitly creating a new Del instance yourself and passing a new named method each time. There are other more "fishy" ways of doing so, but I wouldn't recommend taking those paths just to get a new delegate.
Is there any way how to instantiate delegates that point to different/unique methods inside a loop?
You can't make each loop iteration create a different method because methods are hard-coded into the assembly. Their number is fixed while the loop could be unbounded.
You can make each syntactic appearance of a lambda have a different method by using some kind of hack:
Action<int> x = i => {
if (Environment.CurrentManagedThreadId < 0 /*always false*/)
Console.WriteLine(i + uniqueIntegerHere);
};
This forces each method body to be unique and the compiler cannot ever optimize this away. You can of course pull the body into a helper method.
If you want unique delegates per loop iteration you either need to create methods at runtime or keep a set of statically compiled methods:
void F1() { }
void F2() { }
void F3() { }
...
T4 templates come to mind.
Yet another way similar to the one proposed by #usr. You can force compiler to create a new instance of delegate object using reflection method Delegate.CreateDelegate(type, this, methodInfo). The trick goes at the point where this parameter is always a new object thus forcing myMethod being called on it and thus each delegate actually represents a different context for compiler.
This requires the method for delegation to be inside a separate class, which you can instantiate. I am not sure this requirement fits you actual task. Perhaps you will be inspired for another solution based on this one...
using System.IO;
using System;
using System.Reflection;
using System.Collections.Generic;
class AnyClass
{
delegate void Del(string str);
private static Dictionary<Del, string> dict = new Dictionary<Del, string>();
static void Main()
{
List<Del> listDel = new List<Del>();
int count = 10;
for (int i = 0; i < count; i++)
{
listDel.Add(factory());
dict.Add(listDel[i ], "Delegate " + (i));
}
for (int i = 0; i < count; i++)
{
Console.WriteLine(listDel[i].Method.ToString());
listDel[i].Invoke((i).ToString());
}
Console.ReadLine();
}
public class DelegateEncapsulator
{
private int _number;
public DelegateEncapsulator(int number)
{
_number = number;
}
public void myMethod(string str) {
Console.WriteLine("Delegate " + _number + " " + str);
}
}
private static int delegateCounter = 100;
private static Del factory()
{
var obj = new DelegateEncapsulator(delegateCounter++);
var ret = (Del)Delegate.CreateDelegate(typeof(Del), obj,
typeof(DelegateEncapsulator).GetMethod("myMethod"));
return ret;
}
}
This code adds all delegates into a dictionary. You can play with number elements to be added.
Hope this helps
I used 2 classes, and I need send/receive methods and variables. But when I make an instance of this class it gives me a System.StackOverflowException.
How can fix this problem?
This is my code:
class Setup1
{
Setup2 set2 = new Setup();
int a = 5;
public int myMethod();
{
set2.b = a + 10;
return set2.b;
}
}
class Setup2
{
Setup1 set1 = new Setup();
public int b = 0;
void Show()
{
MessageBox.Show(set1.myMethod());
}
}
You have an infinite recursion.
In the constructor of Setup2() you call the constructor of Setup1(). There you call the constructor of Setup2()and so on, infinitely. Your memory runs out, and your stack overflows.
It seems that you have cyclic constructor calling that leads to stack-overflow exception.
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);
}
}
}