Please take note that this is uncompleted code, but just facing some small issue, as i using a lot of c++ OOP concept. i might have some issue when trying to change from another platform.
I get error when compiled and stated nonstatic method/property error
using System;
public class People
{
string name;
int age;
int height;
public virtual void insertDetail(People stu)
{
Console.Write("Please enter name : ");
stu.name = Console.ReadLine();
Console.Write("Please enter age : ");
while(!int.TryParse(Console.ReadLine(), out stu.age))
{
Console.WriteLine("You enter characters! Please re-insert");
}
Console.Write("Please enter height: ");
while(!int.TryParse(Console.ReadLine(), out stu.height))
{
Console.WriteLine("You enter characters! Please re-insert");
}
}
}
public class Class : People
{
static People[] students = new People[5];
public override void insertDetail(People stu)
{
Console.WriteLine("==================================");
base.insertDetail(stu);
}
public static void Main(string[] args)
{
for (int i = 0; i < students.Length; i++)
{
students[i] = new People();
insertDetail(students[i]);
}
Console.ReadKey();
}
}
As said in comments, you need an instance to use instance method.
Create an instance for Class inside Main
public class Class : People
{
static People[] students = new People[5];
public override void insertDetail(People stu)
{
Console.WriteLine("==================================");
base.insertDetail(stu);
}
public static void Main(string[] args)
{
Class c = new Class(); // this is required to access insertDetail
for (int i = 0; i < students.Length; i++)
{
students[i] = new People();
c.insertDetail(students[i]);
}
Console.ReadKey();
}
}
Check this Demo
You get that error when you make a static call to an instance method like Object.ToString() using the type name as the qualifier when you really need an instance.
First of all never use Class as your class name.
As for the error you need to give more information about what are you trying to do. You have to add static modifier to your method:
public static void insertDetail(People stu)
Or if you want for it to be override than:
public virtual void insertDetail()
{
this.name = "Some name";
//...
}
Related
I am a beginner in C# right now and my task is to write in console all the details of a product. I have to use the struct. I made a Product struct.
The function writeProducts cannot see the prod1 and all of its details.
However I get an error CS0103 that the name doesn't exist in current context and I don't know where I made a mistake.
Sorry, English is not my native language.
namespace project
{
class Program
{
public struct Product
{
public string Name;
public string Type;
public double Pr1pc;
public double Pr1kg;
public int number;
}
static void Main(string[] args)
{
Console.Clear();
Product prod1;
//Prod1
prod1.Name = "Chlyb";
prod1.Type = "szt";
prod1.Pr1pc = 6.30;
prod1.number = 1;
writeProducts();
Console.ReadKey();
Main(args);
}
static void writeProducts()
{
Console.WriteLine("{0}. {0},{0}{0}", prod1.number, prod1.Name, prod1.Pr1pc, prod1.Type);
}
}
}
You declared the variable prod1 in the Main function, so it is not recognized in the writeProducts function. Try to send the prod1 as a parameter to writeProducts like that:
class Program
{
public struct Product
{
public string Name;
public string Type;
public double Pr1pc;
public double Pr1kg;
public int number;
}
static void Main(string[] args)
{
Console.Clear();
Product prod1 = new();
//Prod1
prod1.Name = "Chlyb";
prod1.Type = "szt";
prod1.Pr1pc = 6.30;
prod1.number = 1;
writeProducts(prod1);
Console.ReadKey();
Main(args);
}
static void writeProducts(Product prod)
{
Console.WriteLine("{0}. {0},{0}{0}", prod.number, prod.Name, prod.Pr1pc, prod.Type);
}
}
}
Also notice you need to use the new word when declaring prod1
I am receiving an error: There is no argument given that corresponds to the required formal parameter 'x' of ReadingMaterial.By(string). I'm looking for a little guidance as to why there is an error. Is my syntax wrong, or is there something else I'm missing? I have been trying to learn C# by using some online tutorials and trying to change them up a bit.
namespace ReadingMaterials
{
class Presentation
{
static void Main(string[] args)
{
aForm Form = new aForm(); // available in hardcopy form aForm.availForm
Online O = new Online(); // amtBlogs, amtBooks
Book B = new Book(); // hardCover, softCover
Magazine M = new Magazine(); // numArticles
O.blog(5); //contains 5 blogs
O.oBook(3); //contains 3 online books
O.By("Beck"); //Written by Beck
O.words(678); //with 678 combined words
O.pics(1); // with one pic
Console.WriteLine("The auther {0} ", O.By());
Form.availForm();
B.hardCover(10); //10 hardcover books
B.softCover(2); //2 softcover books
B.By("Bruce"); //Writen by Bruce
B.words(188264); //words combined
B.pics(15); //15 pictures
Form.availForm();
M.articles(5); //5 articles
M.By("Manddi"); //Writen by Manddi
M.words(18064);//combined words
M.pics(81); //81 pictures
Form.availForm();
}
}
class ReadingMaterial
{
protected int amtWords;
string author;
protected int pic;
public void words(int w)
{
amtWords = w;
}
public void By(string x)
{
author = x;
}
public void pics(int pi)
{
pic = pi;
}
}
class Online : ReadingMaterial
{
int amtBlogs;
int amtBooks;
public void blog(int s)
{
amtBlogs = s;
}
public void oBook(int b)
{
amtBooks = b;
}
}
class Book : ReadingMaterial
{
int hard;
int soft;
public void hardCover(int h)
{
hard = h;
}
public void softCover(int s)
{
soft = s;
}
}
class Magazine:ReadingMaterial
{
int numArticles;
public void articles(int a)
{
numArticles = a;
}
}
interface IPrintable
{
void availForm();
}
class aForm : IPrintable
{
public void availForm ()
{
Console.WriteLine("Available in hard copy form!");
}
}
}
Console.WriteLine("The auther {0} ", O.By()); is the culprit. O.By() expects a string, and the By() function sets the author, but doesn't return any string. Since you've set the author using the By() function, you can make the author a public field, and do Console.WriteLine("The auther {0} ", O.author);
The problem is that you are calling By without any parameters in this line:
Console.WriteLine("The auther {0} ", O.By());
You can add a method to get the value instead:
class ReadingMaterial
{
...
public string GetBy()
{
return author;
}
....
}
Anyways, you might want to use properties instead of functions. You can look at the code working in here
class ReadingMaterial
{
public string Author {get;set;}
...
}
static void Main(string[] args)
{
...
O.Author = "Beck"; //Written by Beck
...
Console.WriteLine("The auther {0} ", O.Author);
}
You have defined the By method like this, with a parameter:
public void By(string x)
{
author = x;
}
But you are trying to call it without a parameter:
Console.WriteLine("The auther {0} ", O.By()); // not passing a parameter to 'By()'
If you want to access the author value of ReadingMaterial here then I would suggest making it a public property rather than a private field:
class ReadingMaterial
{
protected int amtWords;
public string Author { get; private set;}
// skipped
public void By(string x)
{
Author = x;
}
All of which kinds of begs the question - why use methods to set the values at all? Why not just use properties, as suggested below by #CarlosGarcia?
I can't figure this out. The problem is that the distance, club, cleanclub, hole, scores and par all say inaccessible due to protection level and I don't know why because I thought I did everything right.
namespace homeworkchap8
{
public class Clubs
{
protected string club;
protected string distance;
protected string cleanclub;
protected string scores;
protected string par;
protected string hole;
public string myclub
{
get { return club; }
set {club = value; }
}
public string mydistance
{
get { return distance; }
set { distance = value; }
}
public string mycleanclub
{
get { return cleanclub; }
set { cleanclub = value; }
}
public string myscore
{
get { return scores; }
set { scores = value; }
}
public string parhole
{
get { return par; }
set { par = value; }
}
public string myhole
{
get { return hole; }
set { hole = value;}
}
}
}
this is the derived class:
namespace homeworkchap8
{
public class SteelClubs : Clubs, ISwingClub
{
public void SwingClub()
{
Console.WriteLine("You hit a " + myclub + " " + mydistance);
}
public void clean()
{
if (mycleanclub != "yes")
{
Console.WriteLine("your club is dirty");
}
else
{
Console.WriteLine("your club is clean");
}
}
public void score()
{
Console.WriteLine("you are on hole " + myhole + " and you scored a " +
myscore + " on a par " + parhole);
}
}
}
This is the interface:
namespace homeworkchap8
{
public interface ISwingClub
{
void SwingClub();
void clean();
void score();
}
}
here is the main code:
namespace homeworkchap8
{
class main
{
static void Main(string[] args)
{
SteelClubs myClub = new SteelClubs();
Console.WriteLine("How far to the hole?");
myClub.distance = Console.ReadLine();
Console.WriteLine("what club are you going to hit?");
myClub.club = Console.ReadLine();
myClub.SwingClub();
SteelClubs mycleanclub = new SteelClubs();
Console.WriteLine("\nDid you clean your club after?");
mycleanclub.cleanclub = Console.ReadLine();
mycleanclub.clean();
SteelClubs myScoreonHole = new SteelClubs();
Console.WriteLine("\nWhat hole are you on?");
myScoreonHole.hole = Console.ReadLine();
Console.WriteLine("What did you score on the hole?");
myScoreonHole.scores = Console.ReadLine();
Console.WriteLine("What is the par of the hole?");
myScoreonHole.par = Console.ReadLine();
myScoreonHole.score();
Console.ReadKey();
}
}
}
In your base class Clubs the following are declared protected
club;
distance;
cleanclub;
scores;
par;
hole;
which means these can only be accessed by the class itself or any class which derives from Clubs.
In your main code, you try to access these outside of the class itself. eg:
Console.WriteLine("How far to the hole?");
myClub.distance = Console.ReadLine();
You have (somewhat correctly) provided public accessors to these variables. eg:
public string mydistance
{
get
{
return distance;
}
set
{
distance = value;
}
}
which means your main code could be changed to
Console.WriteLine("How far to the hole?");
myClub.mydistance = Console.ReadLine();
Dan, it's just you're accessing the protected field instead of properties.
See for example this line in your Main(...):
myClub.distance = Console.ReadLine();
myClub.distance is the protected field, while you wanted to set the property mydistance.
I'm just giving you some hint, I'm not going to correct your code, since this is homework! ;)
myClub.distance = Console.ReadLine();
should be
myClub.mydistance = Console.ReadLine();
use your public properties that you have defined for others as well instead of the protected field members.
In your Main method, you're trying to access, for instance, club (which is protected), when you should be accessing myclub which is the public property that you created.
You organized class interface such that public members begin with "my". Therefore you must use only those members. Instead of
myScoreonHole.hole = Console.ReadLine();
you should write
myScoreonHole.myhole = Console.ReadLine();
It's because you cannot access protected member data through its class instance.
You should correct your code as follows:
namespace homeworkchap8
{
class main
{
static void Main(string[] args)
{
SteelClubs myClub = new SteelClubs();
Console.WriteLine("How far to the hole?");
myClub.mydistance = Console.ReadLine();
Console.WriteLine("what club are you going to hit?");
myClub.myclub = Console.ReadLine();
myClub.SwingClub();
SteelClubs mycleanclub = new SteelClubs();
Console.WriteLine("\nDid you clean your club after?");
mycleanclub.mycleanclub = Console.ReadLine();
mycleanclub.clean();
SteelClubs myScoreonHole = new SteelClubs();
Console.WriteLine("\nWhat hole are you on?");
myScoreonHole.myhole = Console.ReadLine();
Console.WriteLine("What did you score on the hole?");
myScoreonHole.myscore = Console.ReadLine();
Console.WriteLine("What is the par of the hole?");
myScoreonHole.parhole = Console.ReadLine();
myScoreonHole.score();
Console.ReadKey();
}
}
}
You need to use the public properties from Main, and not try to directly change the internal variables.
The reason being you cannot access protected member data through the instance of the class.
Reason why it is not allowed is explained in this blog.
Though it is irrelevant to the case at hand, for the benefit of the next person who arrives at this article through a search engine, if the default constructor of your base class is marked as private, derived classes will incur a CS0122 diagnostic.
Instead, you must promote the private method to protected.
The protected method remains inaccessible to consumers of the derived class unless said class overrides it with a new constructor.
I am unable to understand the output. I have following two classes,
class A
{
public int i = 1;
public virtual void Print()
{
Console.WriteLine("I am A");
}
}
class B:A
{
public int i =2 ;
public override void Print()
{
i++;
Console.WriteLine("I am B");
}
}
Now, when i run the following code,
A a1 = new PolymorphismInDepth.B();
a1.Print();
Console.WriteLine(a1.i);
I get the following output,
I am B
1
why do I get 1? Why not 2?
The base class object a1 is pointing to the Derived object in memory. Hence a1.Print() will call the methods reference, i.e., B().Print() but you cannot access B().i using this A().i.
You need to cast it:
Console.WriteLine(((B)a1).i);
You are confused because you used same variable names. Try this out:
class A
{
public int ai = 1;
public virtual void Print()
{
Console.WriteLine("I am A");
}
}
class B : A
{
public int bi = 2;
public override void Print()
{
bi++;
Console.WriteLine("I am B");
}
}
static void Main(string[] args)
{
A a1 = new B();
a1.Print();
Console.WriteLine(a1.ai);
Console.WriteLine(((B)a1).bi);
Console.Read();
}
Trying to access bi like this should give you a compile time error:
Console.WriteLine(a1.bi); //ERROR: 'A' does not contain a definition for 'bi'...
Update:
To add on to the answer - an implementation like this where you override the base class member variable behavior can also be achieved:
class A
{
private int i = 1;
public virtual int I
{
get { return i; }
}
public virtual void Print()
{
Console.WriteLine("I am A");
}
}
class B : A
{
private int i = 2;
public override int I
{
get { return i; }
}
public override void Print()
{
i++;
Console.WriteLine("I am B");
}
}
A a1 = new B();
a1.Print();
Console.WriteLine(a1.I);
Console.WriteLine(((B)a1).I);
Output:
I am B
3
3
In addition to what Sadiq has said. If you mark your classes as public and build you see that editor is indicating something for variable i in class B. It says that you are hiding base member I and should override with new keyword.
So, if you remove public int i =2 ; from class B then you get output as 2 as you are modifying base variable. But if you declare new i in B then you are creating separate scope of new i in B.
So with current code if you put debugger on line Console.WriteLine(a1.ai);
it clearly shows two i variables one with value 1 and other with value 2. Value 2 is for type B. So you will get 2 only when you are referring i from instance of B.
Hope this clears doubt.
I am a C# teacher and I wrote some automated HW checker for my students.
The students write C# Console Applications. My HW checker is based on input redirection so I can test their code on my own generated input.
The problem is that students sometimes end their program with a Console.ReadKey() instruction (They do so just to make the execution window not close when they ran the program under F5 - Debug). The Console.ReadKey() crashes when ran under input redirection with the following exception:
System.InvalidOperationException: Cannot read keys when either application does not have a console or when console input has been redirected from a file.
Do I have any way to "bypass" this problem (without altering the students code)? Maybe tell Console to ignore ReadKey instructions?
I see a clear case for a Dependency Injection pattern.
Let's build a simple example, with Read, ReadLine and WriteLine functionalities polymorphically: your students must write a homework in which a number given in the Console.ReadLine() must be parsed as int and returned to the Console Window.
Usually a student writes something like:
class Program
{
static void Main(string[] args)
{
var stringValue = Console.ReadLine();
int number;
if (int.TryParse(stringValue, out number))
Console.WriteLine($"The double of {number} is {number * 2}");
else
Console.WriteLine($"Wrong input! '{stringValue}' is not an integer!");
Console.Read();
}
}
Now, instead, create an interface for the Console functionalities:
public interface IOutput
{
void Read();
string ReadLine();
void WriteLine(string text);
}
A student must create a Homework class that wraps all the required homework code, using an IOutput instance in this way:
public class HomeWork
{
private IOutput _output;
public HomeWork(IOutput output)
{
_output = output;
}
public void Run()
{
_output.WriteLine("Give me an integer:");
var stringValue = _output.ReadLine();
int number;
if (int.TryParse(stringValue, out number))
_output.WriteLine($"The double of {number} is {number * 2}");
else
_output.WriteLine($"Wrong input! '{stringValue}' is not an integer!");
_output.Read();
}
}
The Main becomes:
static void Main(string[] args)
{
var h = new HomeWork(new ConsoleOutput());
h.Run();
}
You give them also the ConsoleOutput class:
public class ConsoleOutput : IOutput
{
public void Read()
{
Console.Read();
}
public string ReadLine()
{
return Console.ReadLine();
}
public void WriteLine(string text)
{
Console.WriteLine(text);
}
}
So the use it instead of call directly Console.Read() etc.
The student must pass to you not the entire Application, but only the Homework class.
You can create a test class that use the Homework class with some test implementations of IOutput like the followings:
public abstract class TestOutput : IOutput
{
public TestOutput()
{
Outputs = new List<string>();
}
public void Read()
{
//do nothing?
}
public abstract string ReadLine();
public void WriteLine(string text)
{
Outputs.Add(text);
}
public List<string> Outputs { get; set; }
}
public class TestOutputWithAValidNumber : TestOutput
{
public TestOutputWithAValidNumber(int value)
{
Value = value;
}
public override string ReadLine()
{
return Value.ToString();
}
public int Value { get; }
}
public class TestOutputWithNotValidNumber : TestOutput
{
public TestOutputWithNotValidNumber(string value)
{
Value = value;
}
public override string ReadLine()
{
return Value;
}
public string Value { get; }
}
The test class can be something like this:
[TestClass]
public class TestOutputClass
{
[TestMethod]
public void TestGoodNumber()
{
var testOutput = new TestOutputWithAValidNumber(1234);
var h = new HomeWork(testOutput);
h.Run();
Assert.AreEqual(1234, testOutput.Value);
Assert.AreEqual("Give me an integer:", testOutput.Outputs[0]);
Assert.AreEqual("The double of 1234 is 2468", testOutput.Outputs[1]);
}
[TestMethod]
public void TestWrongNumber()
{
var testOutput = new TestOutputWithNotValidNumber("foo");
var h = new HomeWork(testOutput);
h.Run();
Assert.AreEqual("foo", testOutput.Value);
Assert.AreEqual("Give me an integer:", testOutput.Outputs[0]);
Assert.AreEqual("Wrong input! 'foo' is not an integer!", testOutput.Outputs[1]);
}
}
If you need only to wrap the Console.Read() method, feel free to simplify all this code, but IMHO I thought that a wider view on this possible solution would have been useful anyway.
If the executables are in IL, you can create an easy application that uses ILDASM.
The key point is: disassemble the executable with ILDASM into a text file/stream, look for any call to Console.Read and remove it, than recompile it and run.