Object Oriented Programming help or advice? [closed] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm a novice programmer. I've been writing scripts for about 9 to 11 weeks. Any how I have been buying books per the posting that alot of you guys have recommended. I'm trying to learn "OOP", and it can be little challenging. I have worked the exercises in back of the book. The first exercise told me to make a Console Application program that prompts the user for a type of sport, and the coaches name.
My first question is, did I do this question right?
Are there other ways of doing the same thing, but in different process?
I do realize that I do not have any "try/catches", the exercise told me not to add to this exercise problem. So we will worry about this later.
My code:
static void Main(string[] args)
{
Sport sport01 = new Sport();
sport01.TypeOfSport = GetSportsName();
sport01.CoachesName = GetCoachesName();
Console.WriteLine();
Console.WriteLine(sport01.ToString());
System.Threading.Thread.Sleep(8000);
}
// Prompting user input for type of sport.
public static string GetSportsName()
{
string typeOfSport;
Console.Write("Enter Sports Name : ");
typeOfSport = Console.ReadLine();
return typeOfSport;
}
// Prompting user inout for coaches name.
public static string GetCoachesName()
{
string coachesName;
Console.Write("Enter Coaches Name : ");
coachesName = Console.ReadLine();
return coachesName;
}
class Sport
{
protected string typeOfSport;
protected string coachesName;
public Sport()
{
typeOfSport = "Not Given";
coachesName = "Not Given";
}
public Sport(string typeOS, string coachesN)
{
typeOfSport = typeOS;
coachesName = coachesN;
}
public string TypeOfSport
{
get { return typeOfSport; }
set { typeOfSport = value; }
}
public string CoachesName
{
get { return coachesName; }
set { coachesName = value; }
}
public override string ToString()
{
return "\n" + "\n" +
"\nSports Name : " + typeOfSport +
"\n" +
"\nCoaches Name : " + coachesName;
}
}

It is sometimes better to treat a class as immutable; once created, it never changes. For example:
class Sport
{
protected readonly string typeOfSport;
protected readonly string coachesName;
public Sport(string typeOfSport, string coachesName)
{
this.typeOfSport = typeOfSport;
this.coachesName = coachesName;
}
public string TypeOfSport
{
get { return typeOfSport; }
}
public string CoachesName
{
get { return coachesName; }
}
public override string ToString()
{
return "\n" + "\n" +
"\nSports Name : " + typeOfSport +
"\n" +
"\nCoaches Name : " + coachesName;
}
}
Now you don't have to deal with a Sport that might not have a coach's name or type, and you can get rid of those ugly "Not Given" values:
static void Main(string[] args)
{
var typeOfSport = GetSportsName();
var coachesName = GetCoachesName();
var sport = new Sport(typeOfSport, coachesName);
Console.WriteLine();
Console.WriteLine(sport.ToString());
System.Threading.Thread.Sleep(8000);
}
Notice at no time does a Sport exist that is not valid.
This approach does create more temporary variables, but that is not necessarily a bad thing, and in trade you never have to worry about validating a Sport before using it.
If you do want to keep the class as mutable, as in your original code, I'd advise against using a magic number (i.e. "Not Given") as these are considered a code smell. It would break, for example, if someone ever named their child "Not Given" and he grew up to be a coach. To represent a missing value, the convention is to simply use null.
Also, in general it is advisable to declare a variable the first time you use it, like this:
public static string GetSportsName()
{
Console.Write("Enter Sports Name : ");
var typeOfSport = Console.ReadLine();
return typeOfSport;
}
You'll also notice I changed most of the variable declarations to use var, which allows the compiler to infer the type from the value being assigned.
As a final note, it is poor form to name a variable with a number (e.g. sport01). If you have more than one, put them in an array or List. If you don't have more than one, don't just put an 01 on there, as developers may expect that there is an 02 or 03 somewhere. If you do need two instances that don't logically belong in a list together, give them names describing their purpose, e.g. morningSport and eveningSport or something.

Related

C# - understanding Objects, Classes, and Method interactions

Very, very new programmer here facing some big troubles, I am trying to achieve as follows:
I want to write a very basic program in which the user is prompted to input two double variables, I then want the program to call separate methods, that will perform mathematical operations on those two variables and provide the user the answers.
Example of desired output:
Input First Number
x
Input Second Number
y
Add: z
Subtract: z
My aim in this is to practice using objects, but I am having issues, see this snippet as an example.
class Variables
{
public string First { get; set; }
public string Second { get; set; }
}
class Program
{
Variables inputs = new Variables()
{
Console.WriteLine("Please input first number"),
First = Console.ReadLine(),
Console.WriteLine("Please input second number"),
Second = Console.ReadLine(),
};
static void Main(string[] args)
{
Addthem();
}
public string Addthem()
{
double answer = Convert.ToDouble(inputs.First) + Convert.ToDouble(inputs.Second);
return ("Added: " + answer);
}
}
When trying to call Addthem, I have no 'object reference',
in my object 'inputs', I cannot print to console to prompt user input?
And finally (most mind bogglingly to me), my Main method is not suitable as an entry point for the program, this is what I am MOST clueless on.
Am I even on the right track? As I said very novice so sorry for egregious errors or general ignorance, I am just trying to better understand what I am not seeing in the interactions between Classes, Objects, Methods.
You've got all the ingredients right, but they need to be rearranged to make a good cake. Main() is the entry point, so anything you want to do has to be inside Main() or be called by something inside Main().
A useful concept to know is the difference between a class and an object.
A class is just a specification which says you can have these properties and methods, but you need to create an instance of the class first.
An object is an "instance" of a class and you can call the class methods (functions) through that object. Eg inputs is an instance of the Variables class.
using System;
class Variables
{
public string First { get; set; }
public string Second { get; set; }
public string AddthemInClass()
{
double answer = Convert.ToDouble(First) + Convert.ToDouble(Second);
return ("Added: " + answer);
}
}
class Program
{
static void Main(string[] args)
{
// You had the code to initialise `inputs` outside of Main(),
// so it wouldn't get executed
// It needs to be inside Main()
// `inputs` is created as an instance of the `Variables` class
Variables inputs = new Variables();
Console.WriteLine("Please input first number");
inputs.First = Console.ReadLine();
Console.WriteLine("Please input second number");
inputs.Second = Console.ReadLine();
// You need to tell Addthem() what to work on, ie, pass in `inputs`
var result = Addthem(inputs);
Console.WriteLine( result );
// Or, you could call AddthemInClass through the `inputs` object
// because AddthemInClass is a method of Variables class
var result2 = inputs.AddthemInClass();
Console.WriteLine( result2 );
}
// This should be a static method. If you don't do this, you need to have it
// in a class and call it through an instance of that class
// You could put it inside Variables class - see AddThemInClass()
public static string Addthem(Variables inputs)
{
double answer = Convert.ToDouble(inputs.First) + Convert.ToDouble(inputs.Second);
return ("Added: " + answer);
}
}

Why “this” cannot be set in C# [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I already checked the link "Why can't I set “this” to a value in C#?" and I know that this is read-only. In other words, it (the content) cannot be assigned to another new object. I am just wondering that the philosophy or the consideration of this constraint in C#. If the reason is about to the safety of memory management, C# employs garbage collector and the usage in the future to an object would be determined.
public class TestClass
{
private int Number;
public TestClass()
{
this.Number = 0;
}
public TestClass(TestClass NewTestClass)
{
this = NewTestClass; // CS1604 Cannot assign to 'this' because it is read-only
}
}
As the result, it seems that the members needs to be updated one by one.
public TestClass(TestClass NewTestClass)
{
this.Number = NewTestClass.Number; // Update members one by one.
}
Any comments are welcome.
Note: For clarifying, the C++ part has been removed.
I don't think you are quite familiar with what dereferencing a pointer is.
Let's look at this method:
void TestClass::SetThisTest() {
*this = TestClass(this->IncreaseNumber().GetNumber()); // Assign new object to *this
}
You believe you are replacing the this, but you aren't. You are replacing the contents pointed to by this. Huge difference. *this != this.
Try this:
void TestClass::SetThisTest() {
std::cout << "this' address is " << std::to_address(this) << std::endl;
*this = TestClass(this->IncreaseNumber().GetNumber()); // shallow copy!
std::cout << "Now this' address is " << std::to_address(this) << std::endl;
}
The address doesn't change, but, the values this points do does. You are invoking (in this case) default shallow copy.
You can do this in C# very easily, you just aren't allowed to be that direct about it.
Here is the C# equivalent of your C++ class:
public sealed class ThisTest
{
private int _myNumber;
public ThisTest() { }
public ThisTest(int number) { _myNumber = number; }
public static void ShallowCopy(ThisTest to, ThisTest from)
{
to._myNumber = from._myNumber;
}
public int GetNumber() => _myNumber;
public ThisTest IncreaseNumber()
{
_myNumber += 1;
return this;
}
public void SetThisTest()
{
ShallowCopy(this, new ThisTest(this.IncreaseNumber().GetNumber()));
}
}
Because "this" is a reference to the object you instantiated that is only accessible from the object itself.
Why would "this" need to be anything but self-referential?
var s = new Sample { Title = "My Sample" };
//in this case, I want to see a string representation of "s"
Debug.WriteLine(s.ToString());
//in this case, we might want a copy
var s2 = (Sample)s.MemberwiseClone();
public class Sample
{
public string Title { get; set; }
public override string ToString()
{
//it wouldn't make sense to reference another object's "Title", would it?
return this.Title;
}
}
Is a "keyword" in C# used to refer the current instance of the class.
You can't assign a value to keyword, another example is keyword "base" and we can't assign a value. E.g. base = "text".
We can assign a value to an object through another class that contains the first.
public class TestClassParent
{
private TestClass _testObject;
public TestClassParent(TestClass testOject)
{
this._testObject = testObject;
}
}

How to fix override ToString method

I am setting up a class with a GUI and having issues on this mandatory ToString method I need in my code. I missed 2 classes due to traveling for a family emergency and now just a little lost on what exactly I am doing here.
Honestly, I don't understand much of whats going on, so I am looking for an explanation. But I have tried watching videos and moving around the code to no avail.
class Sandwich
{
public string name = "Tony";
public string meat = "None";
public int tomatoSlices = 1;
public override tomatoSlices.ToString()
{
public double ComputerPrice()
{
return 4.0 + (0.5 * tomatoSlices);
}
}
}
The program should run, but not sure why it isnt. It has something to do with the tomatoSlices integer, I suppose.
As mentioned in the comments you have declared a method inside another method. You need to move the ComputerPrice() outside of the ToString method. Also, you need to remove the tomatoSlices from the ToString definition:
class Sandwich
{
public string name = "Tony";
public string meat = "None";
public int tomatoSlices = 1;
public double ComputerPrice()
{
return 4.0 + (0.5 * tomatoSlices);
}
public override string ToString()
{
return ComputerPrice().ToString();
}
}
Now, when you call sandwich.ToString() it will return the value of ComputerPrices() as a string e.g.:
var sandwich = new Sandwich();
var price = sandwich.ToString();
It's a little hard to tell exactly what you want, but you have a method nested inside another method, which is not legal.
Probably you want to move ComputerPrice() out of the ToString() method, and then implement what you want for ToString() (which is typically the string representation of the class).
Also, you don't specify tomatoSlices as part of the method name; when you override a base class method, you just use the base class method name, which is ToString(). You also have to declare a return type of string for the method.
Other things you may want to do are:
Use public properties instead of fields
Use PascalCase for public members
Use the decimal datatype for working with currency (to avoid rounding errors)
Here's a sample class that addresses all these issues:
class Sandwich
{
public string Name { get; set; }
public string Meat { get; set; }
public int TomatoSlices { get; set; }
public Sandwich()
{
Name = "Tony";
Meat = "None";
TomatoSlices = 1;
}
public override string ToString()
{
return $"This sandwich named {Name} " +
$"has {Meat} meat and {TomatoSlices} slices of " +
$"tomato, for a total cost of {ComputerPrice()}";
// Or just return the price if that's what you want instead:
// return ComputerPrice().ToString();
}
public decimal ComputerPrice()
{
return 4M + 0.5M * TomatoSlices;
}
}

C# Homework. I am looking for an explanation of what is going on

Forgive me for asking what some might think are stupid questions. I am trying to read the code below and make sense out of it.
Why is novel.title used in the main. I understand where I get the title from but why does novel.title used. The other one is what is holding the title information that was entered by the user. Same questions with author, and level.
using System;
using System.Collections.Generic;
using System.Text;
namespace assignment6
{
public class Book
{
protected string title;
public string Title
{
get
{
return title;
}
set
{
title = value;
}
}
protected string author;
public string Author
{
get
{
return author;
}
set
{
author = value;
}
}
public void showBook()
{
Console.WriteLine("The Book you entered is " + title + " by " + author);
}
public Book(string booktyp1, string booktyp2)
{
Console.WriteLine("You will enter data for a " + booktyp1 + " book indicating the " + booktyp2 + " book.");
Console.WriteLine();
}
}
public class Fiction : Book
{
private int level;
public int Level
{
get
{
return level;
}
set
{
level = value;
}
}
public void showFiction()
{
showBook();
Console.WriteLine("Reading level is " + level);
}
public Fiction()
: base("Fiction", "reading level")
{
}
}
public class NonFiction : Book
{
private int pages;
public int Pages
{
get
{
return pages;
}
set
{
pages = value;
}
}
public void showNonFiction()
{
showBook();
Console.WriteLine(pages + " pages");
}
public NonFiction()
: base("NonFiction", "Number of pages")
{
}
}
public class assignment6
{
public static void Main(string[] args)
{
char choice;
Console.Write("Do you want Fiction (F) or Non-Fiction (N)? -->");
choice = Convert.ToChar(Console.ReadLine().ToUpper());
switch (choice)
{
case 'F':
{
Fiction novel = new Fiction();
Console.Write("Enter the book title-->");
novel.Title = Console.ReadLine();
Console.Write("Enter the book author-->");
novel.Author = Console.ReadLine();
Console.Write("Enter the reading level-->");
novel.Level = Convert.ToInt32(Console.ReadLine());
novel.showFiction();
break;
}
case 'N':
{
NonFiction manual = new NonFiction();
Console.Write("Enter the book title-->");
manual.Title = Console.ReadLine();
Console.Write("Enter the book author-->");
manual.Author = Console.ReadLine();
Console.Write("Enter the number of pages-->");
manual.Pages = Convert.ToInt32(Console.ReadLine());
manual.showNonFiction();
break;
}
default:
{
Console.WriteLine("You made an inappropriate entry -- closing program");
break;
}
}
}
}
}
I am sure everyone here know how new I am to programming. I can say this I love it when it works, I hate it when it doesnt and makes me want to quiet.
Title is a property. It actually manages field called title. The value of title is used in the Show... metod.
novel is a Fiction object. Since Fiction inherits from Book, Fiction has a Title and Author property. So what
novel.Title = Console.ReadLine();
is doing is reading input from the console and storing it in the title attribute of your novel object through the Title property.
You should take a look at this Properties Tutorial.
The
protected string title;
cant be accessed directly, but can access through :
public string Title
{
get
{
return title;
}
set
{
title = value;
}
}
Notice title different Title here, You can novel.Title but no novel.title
Title, Author, and Level are attributes of the novel object created at the beginning of the block. The attributes of an object cannot be referenced without a reference to the object itself.
novel is an object, you access properties of objects such as Title, Author, and level.
Put it into persepect:
You have a novel and you are asking the user what is the Title of the novel (novel.Title). Then you ask the user: who is the Author of the novel (novel.Author). Finally, you ask for the Level (novel.Level), (which I'm guessing is like novel difficulty to read) of the novel.
The novel.Title is specifically referring to the Title in the novel object (the one created by Fiction novel = new Fiction();. Say that more Fiction objects were created:
Fiction novel1 = new Fiction();
Fiction novel2 = new Fiction();
Fiction novel3 = new Fiction();
You'd have three Title fields, but how would you indicate which one you're referring to? That's what the prefix is for. In the above example, for instance, you could refer to the Title innovel3 by using novel3.Title.
Your question is a little unclear, but I think you're asking about the difference between novel.title and novel.Title and why one is used over the other.
novel.title is a field that can store some data (in this case, a string of text). novel.Title is a property that provides access to that field. The property itself cannot store any data, only the field can. Fields are considered to be part of the implementation details of the class and it's considered to use a bad idea to directly expose that to the user code. The property is to give the programmer the freedom to later change the implementation without breaking compatibility - it could be as simple as renaming the field or it might be changed to do something else entirely.
Book is the base/super class where derived class are Fiction and NonFiction
Properties of Book are inherited by the two derived class
Two Derived Class declare their own properties.

Updating Object inside/outside Method

Okay,
Maybe this is by design of c# or maybe I am going about this the wrong way.
Please look at the code I have below. I made it where you can copy and paste it into a console app and run it to see what I am talking about.
using System;
namespace ConsoleTest
{
class Program
{
static void Main()
{
var o1 = new oObject
{
Name = "Before Method"
};
var o1b = new oObjectBad
{
Name = "Before Method"
};
Console.WriteLine("Object Bad 1 Before: " + o1b.Name);
oObjectBad o2b = GetNewObjectBad(o1b);
Console.WriteLine("Object Bad 1 After: " + o1b.Name);
Console.WriteLine("Object Bad 2 After: " + o2b.Name);
Console.WriteLine(string.Empty);
Console.WriteLine("Object 1 Before: " + o1.Name);
oObject o2 = GetNewObject(o1);
Console.WriteLine("Object 1 After: " + o1.Name);
Console.WriteLine("Object 2 After: " + o2.Name);
Console.ReadLine();
}
public static oObject GetNewObject(oObject o)
{
oObject newObject = new oObject(o);
newObject.Name = "Changed in Method";
return newObject;
}
public static oObjectBad GetNewObjectBad(oObjectBad o)
{
o.Name = "Changed in Method";
return o;
}
}
class oObject
{
public oObject()
{
}
public oObject(oObject o)
{
Name = o.Name;
}
public string Name { get; set; }
}
class oObjectBad
{
public string Name { get; set; }
}
}
Now, here is what I don't understand.
When I pass in an object to the method, and update the objects property "Name". It then updates the original object which is outside of the method.
The way around this was to create the other object (as shown in code) to make a clone of the object and then update the clone and then return the clone.
So the question is this:
Is there an easier way to pass in an object and update the properties of that object so i can have something like this without it updating the original object.
using System;
namespace ConsoleTest
{
class Program
{
static void Main()
{
var o1 = new oObject
{
Name = "Before Method"
};
Console.WriteLine("Object 1 Before: " + o1.Name);
oObject o2 = GetNewObjectBad(o1);
Console.WriteLine("Object 1 After: " + o1.Name);
Console.WriteLine("Object 2 (New Object) After: " + o2.Name);
Console.ReadLine();
}
public static oObject GetNewObjectBad(oObject o)
{
o.Name = "Changed in Method";
return o;
}
}
class oObject
{
public string Name { get; set; }
}
}
If this is confusing let me know and I will see if I can explain better.
EDIT:
The reason why I am doing this is I need to clone an object in the database and the cloned object will need to have a couple of properties changed. I will then be using the ID from the original object and the new object for other data processing.
Thanks!
I would spend some time researching pass by reference vs. pass by value and then look at why you need to change the name in the local context but not in the original. I have the suspicion you might have some design flaws. I would revisit the problem and see if you can develop a solution with a different approach.
In .NET all objects are reference types unless they descend from ValueType. Typically you would not want to modify instance variables of an object directly anyway. You have much more control if you make instance variables private and then add methods to manipulate the private data.
http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx List of decedents of ValueType.
Why would you want to change the object in a method and not have that data reflected in the calling method? One thing you could do is implement code to track changes, and give the class a method returning the original object with the original data.
Like others have said, this is a value type vs. reference type issue. If you really want to have the object not get changed, you can change your type to a struct. I'm not saying that is the answer though, I don't know your class structure to make an informed opinion on the matter.

Categories

Resources