Using methods on arrays - c#

I am very new to C#, and trying to make a program that counts an array, and I'm having trouble using methods/properties on the array (Reset, PrintCounters, Increment). the problems occur from the for loops and below. Thanks in advance if anyone is able to help.
using System;
namespace CounterTest
{
public class MainClass
{
private static void PrintCounters(Counter[] counters)
{
foreach (Counter c in counters)
{
string name = "";
int value = 0;
Console.WriteLine("{0} is {1}", name, value);
}
}
public static void Main(string[] args)
{
Counter[] myCounters = new Counter[3];
myCounters[0] = new Counter("Counter 1");
myCounters[1] = new Counter("Counter 2");
myCounters[2] = myCounters[0];
for (int i = 0; i < 4; i++)
{
Counter.Increment(myCounters[0]);
}
for (int i = 0; i < 9; i++)
{
Counter.Increment(myCounters[1]);
}
Counter.PrintCounters(myCounters);
Counter.Reset(myCounters[2]);
Counter.PrintCounters(myCounters);
}
}
}
Counter class:
using System;
using System.Collections.Generic;
using System.Text;
namespace CounterTest
{
public class Counter
{
private int _count;
private string _name;
public Counter(string name)
{
_name = name;
_count = 0;
}
public void Increment()
{
_count++;
}
public void Reset()
{
_count = 0;
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public int Value
{
get
{
return _count;
}
set
{
_count = value;
}
}
}
}

The methods you call are not static methods, so they are called like:
for (int i = 0; i < 4; i++)
{
myCounters[0].Increment();
}
for (int i = 0; i < 9; i++)
{
myCounters[1].Increment();
}
MainClass.PrintCounters(myCounters); //this is static
myCounters[2].Reset();
MainClass.PrintCounters(myCounters);

Counter is a type, not an instance, that's why Counter.Increment is an incorrect call (Increment is not a static method).
// Given intance of Counter - myCounters[1] call Increment() method on it
myCounters[1].Increment();
instead of
// Call static method of Counter class - Counter.Increment on instance of Counter
Counter.Increment(myCounters[1]);
etc. It can be something like this:
public static void Main(string[] args)
{
Counter[] myCounters = new Counter[3]
myCounters[0] = new Counter("Counter 1");
myCounters[1] = new Counter("Counter 2");
myCounters[2] = myCounters[0];
for (int i = 0; i < 4; i++)
{
// call Increment on myCounters[0] instance
myCounters[0].Increment();
}
for (int i = 0; i < 9; i++)
{
// call Increment on myCounters[1] instance
myCounters[1].Increment();
}
// PrintCounters method call
PrintCounters(myCounters);
// call Reset on myCounters[2] instance
myCounters[2].Reset();
// PrintCounters method call
PrintCounters(myCounters);
}

You are calling Counter.Increment and then providing a Counter as a parameter. This piece of code assumes Counter is a static class with static methods, which is not the case.
In your for loops, you should be using the code like this:
for (int i = 0; i < 4; i++)
{
myCounters[0].Increment();
}

You use Counter.Increment(myCounters[0]) like Increment was an extention method on Counter.
public static class ExtentionCounter
{
public static void Increment(this Counter cnt)
{
cnt.Value++;
}
}
When with your current definition you should use :
myCounters[0].Increment();

here is the solution for your code. Just compare with yours but see the changes are with ** .
On the PrintCounters since your looping trough the Counters as c you need to call the counter name and the valu with **c.Name and c.Value
using System;
using Test;
namespace teste
{
static class MainClass{
public static void PrintCounters(Counter[] counters)
{
foreach (Counter c in counters)
{
**string name = c.Name;**
**int value = c.Value;**
Console.WriteLine("{0} is {1}", name, value);
}
}
}
class Program
{
static void Main(string[] args)
{
Counter[] myCounters = new Counter[3];
myCounters[0] = new Counter("Counter 1");
myCounters[1] = new Counter("Counter 2");
myCounters[2] = myCounters[0];
for (int i = 0; i < 4; i++) {
**myCounters[0].Increment();**
}
for (int i = 0; i < 9; i++) {
**myCounters[1].Increment();**
}
**MainClass.PrintCounters(myCounters);**
**myCounters[2].Reset();**
**MainClass.PrintCounters(myCounters);**
}
}
}
Also since the myCounters is an instance of Counters you need to call the method of the instance like this:
myCounters[0].Increment()
Same for the other methods as Reset.
To call a static method you dont need to instantiate but in your case you need to do reference to the class to use the method PrintCounters like this:
MainClass.PrintCounters(myCounters);
Also use the keyword this.something to change instance variables.
using System;
using System.Collections.Generic;
using System.Text;
namespace Test
{
public class Counter
{
private int _count;
private string _name;
public Counter(string name)
{
**this._name = name;**
**this._count = 0;**
}
public void Increment()
{
**this._count++;**
}
public void Reset()
{
**this._count = 0;**
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public int Value
{
get
{
return _count;
}
set
{
_count = value;
}
}
}
}
i hope it helps

Related

How to fix this ISeries interface implementation in Class1?

I am developing a series of numbers starting from Setstart(2) function from ISeries interface. I tried to implement this interface in Class1 but it threw an error to me. And I am getting stuck at this error and not been able to figure out to fix this. What am I missing? Please help
I tried to make all functions in the interface public
I tried to remove public access specifier from interface
public interface ISeries {
void Setstart (int a);
int GetNext ();
void Reset ();
}
class Class1 : ISeries {
int val;
void Setstart (int a) {
val = a;
}
int GetNext () {
return val++;
}
void Reset () {
val = 0;
}
static void Main () {
Class1 c = new Class1 ();
c.Setstart (2);
Console.WriteLine (c.GetNext ());
c.Reset ();
Console.WriteLine ();
}
}
I expect the output to be 3 and 0 error is being generated
Your should try something like this.
Because you have to play with one variable so you have to make use of ref `keyword in this case.
and also you have to mark all the method inside a class as a public otherwise you were not be able to access those method inside main
Code:
using System;
namespace StackoverflowProblem
{
public interface ISeries
{
void Setstart(ref int value);
int GetNext(ref int value);
void Reset(ref int value);
}
public class Class1 : ISeries
{
public int val { get; set; }
public void Setstart(ref int value)
{
this.val = value;
}
public int GetNext(ref int value)
{
value = value + 1;
this.val = value;
return this.val;
}
public void Reset(ref int value)
{
// Resetting val.
value = 0;
this.val = value;
}
}
class Program
{
static void Main(string[] args)
{
Class1 c = new Class1();
int value = 2;
c.Setstart(ref value);
Console.WriteLine(" " + c.GetNext(ref value));
c.Reset(ref value);
Console.WriteLine();
}
}
}
Output:
val++ will incriment after returning the current value, ++val will increment first then return the value, you should now get 3, also make it proper scoped to access the methods from outside
class Class1 : ISeries {
int val;
public void Setstart (int a) {
val = a;
}
public int GetNext () {
return ++val;
}
public void Reset () {
val = 0;
}
static void Main () {
Class1 c = new Class1();
c.Setstart(2);
Console.WriteLine (c.GetNext());
c.Reset();
Console.WriteLine ("");
}
}
You need to make your methods public to be accessible outside from class which is missing other than that your code looks fine.
You need to make all the 3 methods public as per your scenario like :
public void Setstart (int a) {
and you will need to first add 1 and then return to get 3 as output as val++ will return the current value and then increment it by 1:
public int GetNext () {
// return val++; // Post increment will not work according to question.
val = val + 1;
return val;
}
Your class with complete implementation of Interface would be like following:
public class Class1 : ISeries {
int val;
public void Setstart (int a) {
val = a;
}
public int GetNext () {
val = val + 1;
return val;
}
public void Reset () {
val = 0;
}
}

Not able to make the value types inside a structure as mutable in c#

I am converting VB6 codes to C# Here I have to convert array of struct into List approach in c# but not able to modify the value in the below sample code getting error as
"Cannot modify the return value of System.Collections.Generic.List<test.Program.TagFieldValue>.this[int]because it is not a variable".
What am I doing wrong.. Is there any other way to do it without converting my type to class?
using System;
using System.Collections.Generic;
namespace test
{
class Program
{
private struct TagFieldValue
{
private int _ID;
public int ID { get { return _ID; } set { _ID = value; } }
}
private List<TagFieldValue> mFieldValues = new List<TagFieldValue>();
static void Main(string[] args)
{
Program obj = new Program();
obj.test();
}
public void test()
{
for (int i = 1; i <= 10; i++)
{
TagFieldValue temp = new TagFieldValue();
temp.ID = i;
mFieldValues.Add(temp);
}
for (int i = 0; i <= 9; i++)
{
mFieldValues[i].ID = mFieldValues[i].ID + 10;
}
for (int i = 0; i <= 9; i++)
{
Console.WriteLine(mFieldValues[i].ID);
}
Console.ReadLine();
}
}
}
Structs are passed as value, not reference. mFieldValues[i].ID = mFieldValues[i].ID + 10; will modify the copy in the list, not the struct itself. To modify the value in the list you need to create new TagFieldValue
for (int i = 0; i <= 9; i++)
{
mFieldValues[i] = new TagFieldValue { ID = mFieldValues[i].ID + 10 };
}
Or change TagFieldValue to class
private class TagFieldValue
{
public int ID { get; set; }
}
Structs aren't that flexible. the inputs can't be defined either, so if you want to do this, you should use a class instead. I had a similar problem and changing it to a class did not give any problems.

Method returning progress of loop

I'm creating a class library with a method, for example, OnetoTen(), which basically is a for loop counting from 1 to 10. What i'm trying to achieve is to call this method from another program and have it output what number/iteration the for loop is currently at.
Is the use of delegates/events the right way to go?
You could use a callback (delegate) or an event.
Example using callback:
class Program
{
static void Main(string[] args)
{
var counter = new Counter();
counter.CountUsingCallback(WriteProgress);
Console.ReadKey();
}
private static void WriteProgress(int progress, int total){
Console.WriteLine("Progress {0}/{1}", progress, total);
}
}
public class Counter
{
public void CountUsingCallback(Action<int, int> callback)
{
for (int i = 0; i < 10; i++)
{
System.Threading.Thread.Sleep(1000);
callback(i + 1, 10);
}
}
}
Example using event:
class Program
{
static void Main(string[] args)
{
var counter = new Counter();
counter.ProgessTick += WriteProgress;
counter.CountUsingEvent();
Console.ReadKey();
}
private static void WriteProgress(int progress, int total){
Console.WriteLine("Progress {0}/{1}", progress, total);
}
}
public class Counter
{
public event Action<int, int> ProgessTick;
public void CountUsingEvent()
{
for (int i = 0; i < 10; i++)
{
System.Threading.Thread.Sleep(1000);
if (ProgessTick != null)
ProgessTick(i + 1, 10);
}
}
}

Make Length property available for my class C#

I want to create class Massive and to add a method for adding two massives. But property Length for my class instances doesn't work.
public static void Add(Massiv mas1, Massiv mas2, ref Massiv mas3)
{
if (mas1.Length != mas2.Length)
{
Console.WriteLine("Error!"); return;
}
for (int i = 0; i < mas.Length; ++i)
{
mas3[i] = mas1[i] + mas2[i];
}
}
How to make it available for my class?
It's my code.
class Massiv
{
public Massiv(int n)
{
mas = new int[n];
Random rand = new Random();
for (int i = 0; i < mas.Length; ++i)
{
mas[i] = rand.Next(0, 10);
}
}
public void ShowAll()
{
Console.WriteLine("Massive: ");
foreach (var elem in mas)
{
Console.Write(elem + " ");
}
Console.WriteLine();
}
public void ShowElement(int index)
{
try
{
Console.WriteLine("mas[{0}] = {1}", index, mas[index]);
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Error!");
}
}
public static void Add(Massiv mas1, Massiv mas2, ref Massiv mas3)
{
if (mas1.Length != mas2.Length)
{
Console.WriteLine("Error!"); return;
}
for (int i = 0; i < mas.Length; ++i)
{
mas3[i] = mas1[i] + mas2[i];
}
}
public int this[int index]
{
get { return mas[index]; }
set { mas[index] = value; }
}
private int[] mas;
}
}
It seems like you have not declared any Length property, therefore, the compiler cannot possibly know one.
Basically, add this to your class:
public int Length {
get {
}
set {
}
}
In the getter, you need to return the value of the property, while in the setter, you will have to change it.
In this case, you seem to want to retrieve the length of your internal array. If you do not need write-access, you can skip the set part:
public int Length {
get {
return mas.Length;
}
}
Just add this property to your class:
public int Length {
get { return mas.Length; }
}
Note it has only a get accessor, which makes it read only (You don't seem to need write access since you initialize the private array in the constructor).
public int Length {
get {
return mas.Length;
}
}

Asynchronous execution in separate domains

How to execute code asynchronously in separate domains ?
For example, I have a method :
public void DoSomething()
{
// do something
}
And I want to execute it in 10 different domains, like this :
for (int i = 0; i < 10; i++)
{
AppDomain domain = AppDomain.CreateDomain("NewDomain - " + i);
domain.ExecuteAsync(DoSomething);
}
I solved my task using this approach :
for (int i = 0; i < options.NumberOfThreads; i++)
{
tasks[i] = Task.Factory.StartNew(() =>
{
using (Isolated<TesterInvoker> isolated = new Isolated<TesterInvoker>())
{
isolated.Value.Invoke();
}
});
}
private class TesterInvoker : MarshalByRefObject
{
public void Invoke()
{
// do something
}
}
private class Isolated<T> : IDisposable
where T : MarshalByRefObject
{
private AppDomain _domain;
private T _value;
public Isolated()
{
Type type = typeof(T);
_domain = AppDomain.CreateDomain("Isolated:" + GetHashCode(),
null, AppDomain.CurrentDomain.SetupInformation);
_value = (T)_domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
}
public T Value
{
get
{
return _value;
}
}
public void Dispose()
{
if (_domain != null)
{
AppDomain.Unload(_domain);
_domain = null;
}
}
}

Categories

Resources