i am a C# beginner, so for now most of my code is inside the Main() method. I want to make my Program more object oriented so I want to move code from Main method to another class reliably(so i can do it with other programs as well).
static void Main()
{
int xLentgh = 20;
int yLength = 20;
Map.MapBuilder(xLentgh,yLength);
int oldPositionX = 0;
int oldPositionY = 0;
int newPositionX = 0;
int newPositionY = 0;
if (oldPositionX == 0)
{
Map.WriteAt(".",newPositionX, newPositionY);
}
for (int i = 0; i < 100; i++)
{
ConsoleKeyInfo KeyStroke;
KeyStroke = Console.ReadKey();
switch (KeyStroke.Key)
{
case ConsoleKey.RightArrow:
{
if (newPositionX < xLentgh-1)
{
oldPositionX = newPositionX;
oldPositionY = newPositionY;
newPositionX++;
}
break;
}
case ConsoleKey.LeftArrow:
{
if (newPositionX > 0)
{
oldPositionX = newPositionX;
oldPositionY = newPositionY;
newPositionX--;
}
break;
}
case ConsoleKey.UpArrow:
{
if (newPositionY > 0)
{
oldPositionX = newPositionX;
oldPositionY = newPositionY;
newPositionY--;
}
break;
}
case ConsoleKey.DownArrow:
{
if (newPositionY < yLength-1)
{
oldPositionX = newPositionX;
oldPositionY = newPositionY;
newPositionY++;
}
break;
}
default: break;
}
Map.WriteAt(".",newPositionX, newPositionY);
Map.WriteAt(" ",oldPositionX, oldPositionY);
}
}
In this code I create a "map" and using the switch statement in the for loop to "track" the position of the cursor. How do I write this code in a new class? I dont know where to start
You can try to create a class named as you want (we will call it RandomNameClass) by declaring it outside of the bloc class Program {}.
You should have something like this :
namespace NameYouGaveToProject
{
class RandomNameClass
{
}
class Program
{
static void Main(string[] args)
{
// Your actual code here
}
}
}
Above or under is fine but prefer having the class Program at the bottom if you write all your code in one file.
There you have your first custom class! Now try to add some functions in it. If you haven't learn about instantiating a class yet, just don't forget to add public static before the returning type of your function.
Example of what you could have :
namespace NameYouGaveToProject
{
class RandomNameClass
{
// Function that doesn't return anything, returns "void"
public static void SayHi()
{
Console.WriteLine("Hi!");
}
// Function that returns a string
public static string ReturnHi()
{
return "Hi!";
}
}
class Program
{
static void Main(string[] args)
{
// Your actual code here
}
}
}
And then you can call them by typing the name of the class, followed by a point and then the name of the function and "()" if there are no parameters to this function (there aren't in my example).
The syntax would be :
// Call the void function
RandomNameClass.SayHi();
// Call the function returning a string
string testVariable = RandomNameClass.ReturnHi();
Note that you can call as often as you want every function
And voilĂ ! You know the basics of creating a class and call functions from this class! Next thing you should learn is how to make functions properly, and then instantiating a class and manage it's content
Related
I'm new to learning C# and am trying to implement the below code however, I am unable to do so, receiving the error "A namespace cannot directly contain members such as fields or methods".
namespace Grades
{
public string LetterGrade
{
get
{
string result;
if (RoundResult(AverageGrade) >= 90)
{
result = "A";
}
else if (RoundResult(AverageGrade) >= 80)
{
result = "B";
}
else if (RoundResult(AverageGrade) >= 70)
{
result = "C";
}
else
{
result = "F";
}
return result;
}
}
private double RoundResult(double result)
{
double r;
r = Math.Round(result);
return r;
}
public class GradeStatistics
{
public float AverageGrade = 50;
public float HighestGrade = 78;
public float LowestGrade = 11;
}
}
What I am trying to accomplish is to create a method called "RoundResult" which will round the "AverageGrade" result. I am merely doing this as an experiment to try and understand how methods interact with each other.
The biggest hurdle I am facing while learning C# is in regards to methods and classes, how to use them correctly, when to place them within an existing class or create there own separate class etc. If someone has any recommended resource that goes into extensive step by step detail on how to implement methods and classes, that would be greatly appreciated.
Edit: Thanks to Reputation Farmer and wazdev for their answers. I'd like to add an additional question....
Why is the "GradeStatistic" method a valid method to call the "AverageGrade" from within the same class yet my "RoundResult" method can not be within the same class?
This error message is occurring because you have two methods directly inside your namespace declaration- they need to be wrapped inside a class.
One possible solution is to create a "GradeCalculator" class and put your two methods inside that ... please note that this is not an optimal solution, but I've tried to modify as little as posssible:
namespace Grades
{
public class GradeCalculator
{
public string LetterGrade
{
get
{
string result;
if (RoundResult(GradeStatistics.AverageGrade) >= 90)
{
result = "A";
}
else if (RoundResult(GradeStatistics.AverageGrade) >= 80)
{
result = "B";
}
else if (RoundResult(GradeStatistics.AverageGrade) >= 70)
{
result = "C";
}
else
{
result = "F";
}
return result;
}
}
private double RoundResult(double result)
{
double r;
r = Math.Round(result);
return r;
}
}
public static class GradeStatistics
{
public static float AverageGrade = 50;
public static float HighestGrade = 78;
public static float LowestGrade = 11;
}
}
As the error says, namespace can't contain methods. You should put them inside a class:
namespace Grades
{
public static class GradeUtil {
public static string LetterGrade { ... }
private static double RoundResult(double result) { ... }
}
public class GradeStatistics
{
public float AverageGrade = 50;
public float HighestGrade = 78;
public float LowestGrade = 11;
}
}
Note the word static. It allows you to call a method without object instance. I.e. you can write GradeUtil.LetterGrade .... It's unclear, cut looks like this is what you intended.
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;
}
}
I have a program with some kind of "Macro Manager" that can (or at least should) save and play macros - one after the other. The macros are functions that the user can select by himself.
For example if the user wants to create a new macro he is going to do the following steps:
Click Button "Create"
Click Button "Select function"
Click another Button (The button holds a function behind it)
Play the macro
So as you can see, the user should be able to choose which function he wants to use dynamically.
I tried using delegates, but I dont really understand them (even though I have read about it)
So this is my code:
The MacroManager (Which holds the macros and plays them one after the other):
namespace ControlCenter
{
public class ControlCenterMacroManager
{
public List<ControlCenterMacro> macroList = new List<ControlCenterMacro>();
public string macroName;
public void runMacroList()
{
Thread t = new Thread(new ThreadStart(runMacroList_t));
t.Start();
}
public void runMacroList_t()
{
foreach (ControlCenterMacro macro in macroList)
{
Console.Write("Playing Macro: ");
macro.Run();
}
}
}
}
This would be the macro:
namespace ControlCenter
{
public class ControlCenterMacro
{
public bool isTimeout=false;
public int timemilli=0;
public delegate int macroAction();
public macroAction action;
public void Run()
{
if (isTimeout)
{
Console.Write("Waiting " + timemilli + " milliseconds ");
Thread.Sleep(timemilli / 4);
Console.Write(".");
Thread.Sleep(timemilli / 4);
Console.Write(".");
Thread.Sleep(timemilli / 4);
Console.Write(".");
Thread.Sleep(timemilli / 4);
Console.WriteLine(" done");
}
else
{
Console.WriteLine("Playing action " + action.ToString());
action();
}
}
}
}
And this is one of the possible functions I want to lay behind it (which is located in another class in another project):
public int turnOn()
{
Console.WriteLine("Einschalten:");
if(HomeMaticHttpRequest.sendRequest(this.url + "statechange.cgi?ise_id=" + this.RecieverId + "&new_value=true")!=null)
return 0;
return 1;
}
Does anybody know how I can solve this problem without too much hardcoding? (Want to keep it relatively dynamical)
Here is a small example stripped down to its essentials.
The Macro:
public class Macro
{
public delegate int macroAction();
public macroAction action;
public void Run()
{
action();
}
}
A container class with different methods:
public class Container
{
public int turnOn()
{
Console.WriteLine("Einschalten");
return 1;
}
public int turnOff()
{
Console.WriteLine("Ausschalten");
return 1;
}
}
And a small test programm which assigns different methods:
void Main()
{
Container c = new Container();
List<Macro> MacroList = new List<Macro>();
for (int i = 0; i < 10; i++)
{
Macro m = new Macro();
if (i % 2 == 0)
{
m.action = c.turnOn;
}
else
{
m.action = c.turnOff;
}
MacroList.Add(m);
}
foreach (var m in MacroList)
{
m.Run();
}
}
For the more general version I have to comeback tomorrow, gotta catch my train ;)
I'm making a game using Monogame, and I've been trying to figure out how to implement a function that acts similarly to AS3's and GML's with statement.
So far I have a system that works, but not entirely the way I want it to. I store my GameObjects in a Dictionary of Lists. This is so I can get to the specific type of object I want to access without having to loop through a list of ALL objects. The key used is the name of the type.
public static Dictionary<string, List<GameObject>> All =
new Dictionary<string, List<GameObject>>();
I access all of a specific type of object using AllOf. If a List containing that type exists in the Dictionary, it returns that List, else it returns an empty list.
public static List<GameObject> AllOf(Type type)
{
string key = type.Name;
if(All.ContainsKey(key))
{
return All[key];
}
return new List<GameObject>();
}
An example of how these are implemented
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
}
}
But I'd rather use something similar to the AS3/GML with statement, which would also allow for other, non-member codes to be executed.
with(typeof(Dummy))
{
Update(gameTime);
foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
Is there a way to accomplish this? My end goal is just to make my code look a little cleaner, and make it easier to make a lot of changes without having to type out a for loop each time.
No such syntax exists in C#, but you can access methods within the for that have nothing to do with the collection:
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
}
Note that you can also use foreach, which is a little cleaner if you don't need the indexer:
foreach(var item in list)
{
item.Update(gameTime);
item.foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
try
using(Object myObject = new Object()){
}
i think this might be what your looking to use?
I have a small solution for this use case. This may be a bit of a necropost, but it is a pretty neat solution. Additionally, I think all of the C# features that are required existed back when this question was asked.
You can do something very similar to the GML with(x){} by using some form of delegate as a parameter to a static method, and passing a lambda as that parameter. The function can even be genericised, and you can call it without the class name by the using static statement. You will need to explicitly provide the typed/named parameter, but it is possible. You would need to hook it up to your own types, but the general idea is:
namespace NiftyStuff {
public static class With {
public static void with<T>(Action<T> proc) where T : GameObj {
var typeName = typeof(T).Name;
foreach (var item in GameObj.AllOf(typeName)) { proc((T)item); }
}
}
public class GameObj {
private static Dictionary<string, List<GameObj>> All = new Dictionary<string, List<GameObj>>();
public static List<GameObj> AllOf(string name) {
return All.ContainsKey(name) ? All[name] : null;
}
public static void Add(GameObj foo) {
string typeName = foo.GetType().Name;
List<GameObj> foos = All.ContainsKey(typeName) ? All[typeName] : (All[typeName] = new List<GameObj>());
foos.Add(foo);
}
public float x, y, angle;
public GameObj() { x = y = angle = 0; }
public void Destroy() { AllOf(GetType().Name)?.Remove(this); }
}
public class Enemy : GameObj {
public float maxHealth, curHealth;
public Enemy() : base() { maxHealth = curHealth = 300; }
public Enemy(float health) : base() { maxHealth = curHealth = health; }
public bool Damage(float amt) {
if (curHealth > 0) {
curHealth -= amt;
return curHealth <= 0;
}
return false;
}
}
public class Pumpkin : GameObj {
public bool exists = false;
public Pumpkin() : base() { exists = true; }
public bool LookAt() { return (exists = !exists); }
}
}
Actually using the above code would work as follows:
using NiftyStuff;
using static NiftyStuff.With;
//...
with ((Enemy e) => {
if (e.Damage(50)) {
Log("Made a kill!"); // Whatever log function you have...
}
});
with ((Pumpkin p) => {
if (p.LookAt()) {
Log("You see the pumpkin");
} else {
Log("You no longer see the pumpkin");
}
});
While not exactly like GML's with statement, it would at least let you run code against all of the registered objects of some type.
One important note is that you can't destroy objects inside of a with this way (due to concurrent modification of a collection while iterating it). You would need to collect all objects to be destroyed, and then remove them from the list in All, typically in a game loop this is done at the end of a frame.
Hope this helps, despite being 2 years out of date.
i have app with gui
I put function checkproxy() in Form1.cs it works correctly and i want move function checkproxy() to other class but if i put checkproxy() in other class it will error with Invoke and richTextBox3
namespace test3
{
public partial class Form1 : Form
{
public bool continueThreads = false;
string[] proxyList = null;
List<Thread> threadList = new List<Thread>();
int proxynum = 0;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int n = (int)numericUpDown1.Value;
Thread[] tl = new Thread[n + 1];
threadList = tl.ToList();
for (int i = 0; i <= n; i++)
{
threadList[i] = new Thread(new ThreadStart(checkproxy));
}
for (int i = 0; i <= n; i++)
{
threadList[i].Start();
}
continueThreads = true;
proxyList = richTextBox1.Lines;
}
public void checkproxy()
{
while (continueThreads)
{
if (proxynum >= proxyList.Length)
{
continueThreads = false;
}
if (proxynum < proxyList.Length)
{
string proxy = proxyList[proxynum];
proxynum += 1;
string info = "";
try
{
Thread.Sleep(1000);
info += "Live || " + proxy + Environment.NewLine;
this.Invoke(new Action(() => richTextBox3.Text += info));
}
catch
{
}
}
}
}
}
}
this is screenshot error
Your method checkproxy uses Form1 class members (continueThreads, proxynum and others) directly.
If you really want do move it outside of this class (I'm not sure it is good idea since this method looks very closely related to your class) - you need to refactor this method and pass all class members it uses as method input parameters like
public void checkproxy(bool continueThreads.....)
Because this is a System.Windows.Forms.Form in original context.
To be able to Invoke interface update from another thread/async task, you need to use it (as you did correctly in your original code).
But once you move the function into separate class, there is no more notion of a Conntrol or Form there, so this is a class itself, which does not have Invoke implementation.
One possible solution: you need to refactor your method in a way, that he is able to call Form's function, that internally calls Invoke.