classes and functions - c#

I have 3 classes named maths, alphabets and main. The Maths Class contains Add function and alphabet class contains a function same as Maths class. But the third class is for calling the function which is used for calling the above functions defined in the above classes.
How it will work?

If the functions are static you'll have to explicitly tell which class they belong to - the compiler will be unable to resolve otherwise:
Maths.Add();
If they are not static the compiler will determine this based on the object type:
Maths maths = new Maths();
maths.Add(); // the necessary class and function will be resolved automatically

Is this what you mean?
public class Maths
{
public Maths() { }
public Double Add(Double numberOne, Double numberTwo)
{
return numberOne + numberTwo;
}
}
public class Alphabet
{
public Alaphabet() { }
public String Add(Char characterOne, Char characterTwo)
{
return characterOne.ToString() + characterTwo.ToString();
}
}
public void Main()
{
Alphabet alaphatbet = new Alphabet();
String alphaAdd = alphabet.Add('a', 'b'); // Gives "ab"
Maths maths = new Maths();
Double mathsAdd = maths.Add(10, 5); // Gives 15
}

By using an interface that defines an Add function and having Math and alphabets implement that interface.

C# programs do not contain "functions", but instead methods, which are attached to classes. So you call Math.Add or Alphabet.Add. Conflicting function names do not exist, in C#, for that reason. Conflicting class names are resolved by name spaces.

Related

C# Abstract methods, readonly properties

I have an assignment (bunch of oop stuff, polymorphism and inheritance) and amongst other things I have to do the following:
I need to add an abstract method to the class Vehicle (called calculateOccupancy()) which has to return the % of the leftover space in a vehicle. I then have to implement that in my derived classes. The issue here is, I have 3 derived classes, two of them have 2 attributes and one has 3. So how do I make my abstract method, so that it can accept 2 or 3 arguments.
I have to add a unchangeable property to the class Person, and the property has to return the first letter of the name and surname, divided by a dot.
namespace Example
{
abstract class Vehicle
{
//class member variables, most likely unnecessary for the questions
private Person driver;
private string vehicleBrand;
private string vehicleType;
private double fuelConsumption;
private double gasTankSize;
private string fuelType;
//the default constructor
public Vehicle()
{}
//The abstract method from question 2
// how to make it so that it wont error when I need to
//put in 3 variables instead of two, meaning, how would I add int c
public abstract double calculateOccupancy (int a, int b);
//The derived class that implements the method
class Bus : Vehicle
{
private int allSeats;
private int allStandingSeats;
private int busPassengers; //the number of passengers
//the constructor
public Bus (int a, int b, int c)
{
allSeats=a;
allStandingSeats=b;
busPassengers=c;
}
//the abstract method
// needs to take in int b (standing seats)
public override double calculateOccupancy(int a, int c)
{
//this code calculates the leftover space in the vehicle
double busSpace=(busPassengers*100) / allSeats;
return busSpace;
//same code for the leftover standing space (int c)
}
}
}
class Person
{
protected string name;
protected string lastName;
//question 1
//properties for char gender
protected char gender;
//question 3
protected readonly string initials;
//the code errors, at the get/set
public char Gender
{
get{ return gender; }
set {gender=value;}
}
/*and the property im not sure how to make
public string Initials{}
*/
}
I hope the comments add some clarity, rather than confusion, thank you for your help everybody.
Assumption going forward - I threw some of your variable names into Google Translate and it seems to be Slovenian. I'm assuming that going forward which helped me make some clarity of what your code does.
1) Replace - If you already have a variable that is a char representing spol then I believe you're supposed to use the new enum type you are to create to represent it.
public enum Spol
{
Moski = 0,
Zenska = 1
}
Change:
protected char spol;
public char Spol
{
get{ return spol; }
set {spol=value;}
}
To: public Spol Spol { get; set; }
2) Defaults & Conditions - Use int c = 0 as your 3rd parameter and use a formula/algorithm that ignores it if it is the default value.
3) Getters - This property doesn't have a setter and therefore cannot be changed (directly).
public string GiveThisAName
{
get
{
if (String.IsNullOrWhiteSpace(ime))
{
return null;
}
if (String.IsNullOrWhiteSpace(priimek))
{
return null;
}
return ime[0] + '.' + priimek[0];
}
}
Notes
1) Heavily recommend making the parameters of your capacity function (i.e. izracunajZasedenost(int a, int b)) to be named something useful (i.e. a name descriptive of what they do) other than a and b.
2) For the record, #1 seems more like an appropriate question for your instructor, teacher, or whoever gave you this assignment.
Give the "optional" values a value when you create the abstract method
public abstract double izracunajZasedenost (int a = -1, int b = -1)
{
if (a == -1){
//do method with ignoring a
}
};

New method cannot be accessed by new object

Who ya gonna call?
Unrelated code to pose the problem. Not the best editor tool so being terse. Thanks.
A new method that is part of the derived class cannot be accessed by the new
object. All the Intellisense sees are the abstract parts of the base class. Typing them in and running them gets an error. If methods and fields can't be added what is the point of base to derived and on down. I have searched all examples and come up empty.
public class SalesEmployee : Employee
{
public decimal salesbonus; // Additional field
public SalesEmployee(string name, decimal basepay, decimal salesbonus)
{
this.salesbonus = salesbonus; // Create new field
}
public override decimal CalculatePay() // Override abstract
{
return basepay + salesbonus;
}
public decimal CalculateExtraBonus() // Not an override
{
return basepay + (0.5 * salesbonus); // Belongs to this class only
}
}
static void Main()
{
// Create new employee.
SalesEmployee employee1 = new SalesEmployee("Alice", 1000, 500);
decimal = employee1.CalculateExtraBonus(); // Can't see the new method
// Derived class cannot get to new method.
}
I'm thinking of trying the following. Typing out questions really helps.
{ SalesEmployee salesEmpInstance = employee1
decimal = salesEmpInstance.CalculateExtraBonus()
// Maybe this could see the method.
I'll ignore the syntax errors and assume you have it right in your actual code. However it looks like you forgot to call the parents constructor ("base") on your derived class constructor and then tried to access a variable only instantiated by the parent. Also you need to cast the literal "0.5" as a decimal.
You can read more about "base" on msdn
Working code is below. Output is 1250.
using System;
public abstract class Employee
{
public string name;
public decimal basepay;
public Employee(string name, decimal basepay)
{
this.name = name;
this.basepay = basepay;
}
public abstract decimal CalculatePay();
}
public class SalesEmployee : Employee
{
public decimal salesbonus; // Additional field
// -->ERROR HERE, You forgot to call the base and instantiate
// the fields of the parent.
public SalesEmployee(string name, decimal basepay, decimal salesbonus): base(name, basepay)
{
this.salesbonus = salesbonus; // Create new field
}
public override decimal CalculatePay() // Override abstract
{
return basepay + salesbonus;
}
public decimal CalculateExtraBonus() // Not an override
{
return basepay + ((decimal)0.5 * salesbonus); // Belongs to this class only
}
}
class Program
{
static void Main(string[] args)
{
SalesEmployee employee1 = new SalesEmployee("Alice", 1000, 500);
decimal aliceBonus = employee1.CalculateExtraBonus();
Console.WriteLine(aliceBonus);
}
}
Your code looks fine, I recommend you:
Remove the reference to the first class library from your new project.
Rebuild your first class library
Reference again the first class library dll file in your new project, maybe you referenced to an older version of the dll. You should reference to the last created dll of first class library
Correct your code like this
.
{
SalesEmployee employee1 = new SalesEmployee("Alice", 1000, 500);
SalesEmployee salesEmpInstance = employee1 ;
decimal result = salesEmpInstance.CalculateExtraBonus();
}
Anyway if you have not any reference in this case. Compair the following codes with your code. I tested it. It works...
Note1: You should use base in your constructor to pass name and basepay to their corresponding fields in base class.
Note2: Now Rebuild your project, have you any error? I have not! Have you VS Intellisense problem yet?

how to write the methods inside the enum in c# [duplicate]

In Java, it's possible to have methods inside an enum.
Is there such possibility in C# or is it just a string collection and that's it?
I tried to override ToString() but it does not compile. Does someone have a simple code sample?
You can write extension methods for enum types:
enum Stuff
{
Thing1,
Thing2
}
static class StuffMethods
{
public static String GetString(this Stuff s1)
{
switch (s1)
{
case Stuff.Thing1:
return "Yeah!";
case Stuff.Thing2:
return "Okay!";
default:
return "What?!";
}
}
}
class Program
{
static void Main(string[] args)
{
Stuff thing = Stuff.Thing1;
String str = thing.GetString();
}
}
You can write an extension method for your enum:
How to: Create a New Method for an Enumeration (C# Programming Guide)
Another option is to use the Enumeration Class created by Jimmy Bogard.
Basically, you must create a class that inherits from his Enumeration. Example:
public class EmployeeType : Enumeration
{
public static readonly EmployeeType Manager
= new EmployeeType(0, "Manager");
public static readonly EmployeeType Servant
= new EmployeeType(1, "Servant");
public static readonly EmployeeType Assistant
= new EmployeeType(2, "Assistant to the Regional Manager");
private EmployeeType() { }
private EmployeeType(int value, string displayName) : base(value, displayName) { }
// Your method...
public override string ToString()
{
return $"{value} - {displayName}!";
}
}
Then you can use it like an enum, with the possibility to put methods inside it (among another things):
EmployeeType.Manager.ToString();
//0 - Manager
EmployeeType.Servant.ToString();
//1 - Servant
EmployeeType.Assistant.ToString();
//2 - Assistant to the Regional Manager
You can download it with NuGet.
Although this implementation is not native in the language, the syntax (construction and usage) is pretty close to languages that implement enums natively better than C# (Kotlin for example).
Nope. You can create a class, then add a bunch of properties to the class to somewhat emulate an enum, but thats not really the same thing.
class MyClass
{
public string MyString1 { get{ return "one";} }
public string MyString2 { get{ return "two";} }
public string MyString3 { get{ return "three";} }
public void MyMethod()
{
// do something.
}
}
A better pattern would be to put your methods in a class separate from your emum.
Since I came across, and needed the exact opposite of enum to string, here is a Generic solution:
static class EnumExtensions {
public static T GetEnum<T>(this string itemName) {
return (T) Enum.Parse(typeof(T), itemName, true);
}
}
This also ignores case and is very handy for parsing REST-Response to your enum to obtain more type safety.
Hopefully it helps someone
C# Does not allow use of methods in enumerators as it is not a class based principle, but rather an 2 dimensional array with a string and value.
Use of classes is highly discouraged by Microsoft in this case, use (data)struct(ures) instead; The STRUCT is intended as a light class for data and its handlers and can handle functions just fine. C# and its compiler don't have the tracking and efficiency capabilities as one knows from JAVA, where the more times a certain class / method is used the faster it runs and its use becomes 'anticipated'. C# simply doesn't have that, so to differentiate, use STRUCT instead of CLASS.

Refactoring class to get rid of switch case

Say I have a class like this for calculating the cost of travelling different distances with different modes of transportation:
public class TransportationCostCalculator
{
public double DistanceToDestination { get; set; }
public decimal CostOfTravel(string transportMethod)
{
switch (transportMethod)
{
case "Bicycle":
return (decimal)(DistanceToDestination * 1);
case "Bus":
return (decimal)(DistanceToDestination * 2);
case "Car":
return (decimal)(DistanceToDestination * 3);
default:
throw new ArgumentOutOfRangeException();
}
}
This is fine and all, but switch cases can be a nightmare to maintenance wise, and what if I want to use airplane or train later on? Then I have to change the above class. What alternative to a switch case could I use here and any hints to how?
I'm imagining using it in a console application like this which would be run from the command-line with arguments for what kind of transportation vehicle you want to use, and the distance you want to travel:
class Program
{
static void Main(string[] args)
{
if(args.Length < 2)
{
Console.WriteLine("Not enough arguments to run this program");
Console.ReadLine();
}
else
{
var transportMethod = args[0];
var distance = args[1];
var calculator = new TransportCostCalculator { DistanceToDestination = double.Parse(distance) };
var result = calculator.CostOfTravel(transportMethod);
Console.WriteLine(result);
Console.ReadLine();
}
}
}
Any hints greatly appreciated!
You could do something like this:
public class TransportationCostCalculator {
Dictionary<string,double> _travelModifier;
TransportationCostCalculator()
{
_travelModifier = new Dictionary<string,double> ();
_travelModifier.Add("bicycle", 1);
_travelModifier.Add("bus", 2);
_travelModifier.Add("car", 3);
}
public decimal CostOfTravel(string transportationMethod) =>
(decimal) _travelModifier[transportationMethod] * DistanceToDestination;
}
You could then load the transportation type and it's modifier in a configuration file instead of using a switch statement. I put it in the constructor to show the example, but it could be loaded from anywhere. I would also probably make the Dictionary static and only load it once. There is no need to keep populating it each time you create a new TransportationCostCalculator especially if it isn't going to change during runtime.
As noted above, here is how you could load it by a configuration file:
void Main()
{
// By Hard coding.
/*
TransportationCostCalculator.AddTravelModifier("bicycle", 1);
TransportationCostCalculator.AddTravelModifier("bus", 2);
TransportationCostCalculator.AddTravelModifier("car", 3);
*/
//By File
//assuming file is: name,value
System.IO.File.ReadAllLines("C:\\temp\\modifiers.txt")
.ToList().ForEach(line =>
{
var parts = line.Split(',');
TransportationCostCalculator.AddTravelModifier
(parts[0], Double.Parse(parts[1]));
}
);
}
public class TransportationCostCalculator {
static Dictionary<string,double> _travelModifier =
new Dictionary<string,double> ();
public static void AddTravelModifier(string name, double modifier)
{
if (_travelModifier.ContainsKey(name))
{
throw new Exception($"{name} already exists in dictionary.");
}
_travelModifier.Add(name, modifier);
}
public double DistanceToDestination { get; set; }
TransportationCostCalculator()
{
_travelModifier = new Dictionary<string,double> ();
}
public decimal CostOfTravel(string transportationMethod) =>
(decimal)( _travelModifier[transportationMethod] * DistanceToDestination);
}
Edit: It was mentioned in the comments that this wouldn't allow the equation to be modified if it ever needed to change without updating the code, so I wrote up a post about how to do it here: https://kemiller2002.github.io/2016/03/07/Configuring-Logic.html.
It looks to me like any solution based on your current method is flawed in one critical way: No matter how you slice it, you're putting data in your code. This means every time you want to change any of these numbers, add a new vehicle type, etc., you have to edit code, and then recompile, distribute a patch, etc.
What you really should be doing is putting that data where it belongs - in a separate, non-compiled file. You can use XML, JSON, some form of database, or even just a simple config file. Encrypt it if you want, not necessarily needed.
Then you'd simply write a parser that reads the file and creates a map of vehicle type to cost multiplier or whatever other properties you want to save. Adding a new vehicle would be as simple as updating your data file. No need edit code or recompile, etc. Much more robust and easier to maintain if you plan to add stuff in the future.
Sounds like a good candidate for dependency-injection:
interface ITransportation {
decimal CalcCosts(double distance);
}
class Bus : ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 2); }
}
class Bicycle : ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 1); }
}
class Car: ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 3); }
}
Now you can easily create a new class Plane:
class Plane : ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 4); }
}
Now create a constrcutor for your calculator that expects an instance of ITransportation. Within your CostOfTravel-method you can now call ITransportation.CalcCosts(DistanceToDestination).
var calculator = new TransportationCostCalculator(new Plane());
This has the advantage that you can exchange your actual transportation-instance without any code-change to your TransportationCostCalculator-class.
To complete this design you might also create a TransportationFactory as follows:
class TransportationFactory {
ITransportation Create(string type) {
switch case "Bus": return new Bus(); break
// ...
}
Which you call like
ITransportation t = myFactory.Create("Bus");
TransportationCostCalculator calculator = new TransportationCostCalculator(t);
var result = myCalculator.CostOfTravel(50);
You could define an abstract class like this, and have each TransportationMethod extend the abstract class:
abstract class TransportationMethod {
public TransportationMethod() {
// constructor logic
}
abstract public double travelCost(double distance);
}
class Bicycle : TransportationMethod {
public Bicycle() : base() { }
override public double travelCost(double distance) {
return distance * 1;
}
}
class Bus : TransportationMethod {
public Bus() : base() { }
override public double travelCost(double distance) {
return distance * 2;
}
}
class Car : TransportationMethod {
public Car() : base() { }
override public double travelCost(double distance) {
return distance * 3;
}
}
So in your actual method call, it could be rewritten like this:
public decimal CostOfTravel(TransportationMethod t) {
return t.travelCost(DistanceToDestination);
}
You could use a strategy class for each type of travel. But, then you'd probably need a factory to create the strategy based upon the transport method which would likely have a switch statement to return the appropriate calculator.
public class CalculatorFactory {
public static ICalculator CreateCalculator(string transportType) {
switch (transportType) {
case "car":
return new CarCalculator();
...
public class CarCalculator : ICalculator {
public decimal Calc(double distance) {
return distance * 1;
}
}
....
You can make a Dictionary that returns a multiplier based on transport.
public class TransportationCostCalculator
{
Dictionary<string, int> multiplierDictionary;
TransportationCostCalculator ()
{
var multiplierDictionary= new Dictionary<string, int> ();
dictionary.Add ("Bicycle", 1);
dictionary.Add ("Bus", 2);
....
}
public decimal CostOfTravel(string transportMethod)
{
return (decimal) (multiplierDictionary[transportMethod] * DistanceToDestination);
}
I think the answer is some kind of database.
If you use some, the TransportCostCalculator ask the database for the multiplayer to the given transportmethod.
The database may be a text-file or an xml or an SQL-server. Simply a key-value-pair.
If you want to use code-only there is - tmo - no way to avoid the translation from transportmethod to multiplayer (or cost). So some kind of swicht is needed.
With the database you put the dictionary out of your code and you must not change your code to apply new transportmethods or change the values.
This is a case for the strategy design pattern. Create a base class, say TravelCostCalculator, then develop classes for each mode of travel you will consider, each overriding a common method, Calculate(double). You can then instantiate the specific TravelCostCalculator as needed using the factory pattern.
The trick is in how to construct the factory (without a switch statement). The way I do this is by having a static class constructor (public static Classname() - not an instance constructor) that registers each strategy class with the factory in a Dictionary<string, Type>.
Since C# does not run class constructors deterministically (like C++ does in most cases) you have to explicitly run them to ensure they will run. This could be done in the main program or in the factory constructor. The downside is that if you add a strategy class, you must also add it to the list of constructors to be run. You can either create a static method that must be run (Touch or Register) or you can also use System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor.
class Derived : Base
{
public static Derived()
{
Factory.Register(typeof(Derived));
}
}
// this could also be done with generics rather than Type class
class Factory
{
public static Register(Type t)
{
RegisteredTypes[t.Name] = t;
}
protected Dictionary<string, Type t> RegisteredTypes;
public static Base Instantiate(string typeName)
{
if (!RegisteredTypes.ContainsKey(typeName))
return null;
return (Base) Activator.CreateInstance(RegisteredTypes[typeName]);
}
}
I prefer to use Enum for that like this:
public enum TransportMethod
{
Bicycle = 1,
Bus = 2,
Car = 3
}
And use it like this method:
public decimal CostOfTravel(string transportMethod)
{
var tmValue = (int)Enum.Parse(typeof(TransportMethod), transportMethod);
return DistanceToDestination * tmValue;
}
Note that above method is case-sensitive, So you can capitalize first char;
Related Answer
It was said before but i want to give related topic another shot.
This is a good example for reflection.
"Reflection objects are used for obtaining type information at runtime. The classes that give access to the metadata of a running program are in the System.Reflection namespace."
By using reflection, you will avoid compiling code if another switch type such as train is wanted to add the program. You will solve the problem on the fly by using a config file.
I recently solved a similar problem with strategy patttern, by using dependency injection but I still end up with switch statement. It doesnt solve your problem this way. Method suggested by tyson still needs recompile if a new type added to dictionary.
An example of what i am talking about:
Dynamic Loading of Custom Configuration XML using Reflection in C# :
http://technico.qnownow.com/dynamic-loading-of-custom-configuration-xml-using-reflection-in-c/
Define a look up table array 3 by 2.
Look up rate value in array cell adjacent to transport type.
Calculate cost based on rate.

C# Return Value, But keep getting error. Why?

Hello fellow stackoverflow members!
I'm very new to the C# language transfer from Java, Obj-C.
It looks pretty same as Java, but I have trouble issue in very simple thing.
I have created two individual class files, Class-A and Class-Human.
Specification for Class-A
it contains the static main method declared.And I've tried to create the new instance of Class-Human.
public static void main(String args[])
{
Human human = new Human("Yoon Lee", 99);
int expected = human.getNetID; //<-gets the error at this moment.
}
Specification for Class-Human
namespace Class-A
{
public class Human
{
public String name;
public int netId;
public Human(String name, int netId)
{
this.name = name;
this.netId = netId;
}
public int getNetID()
{
return netId;
}
}
Why can't copy over into local variable?
The compiler prompts me the error of
'Cannot convert method group of 'getNetID' delegate blah blah'
Thank you.
Change the method-call to:
int expected = human.getNetID();
In C#, method-calls require parantheses () containing a comma-separated list of arguments. In this case, the getNetID method is parameterless; but the empty parantheses are still required to indicate that your intention is to invoke the method (as opposed to, for example, converting the method-group to a delegate-type).
Additionally, as others have pointed out, there is a mismatch betweem the return-type of the method and the variable you're assigning its value to, which you're going to have to resolve somehow (change both the field-type and method return-type to int / parse the string as an integer, etc.).
On another note, C# natively supports properties for getter-setter semantics, so the idiomatic way of writing this would be something like:
//hyphens are not valid in identifiers
namespace ClassA
{
public class Human
{
// these properties are publicly gettable but can only be set privately
public string Name { get; private set; }
public int NetId { get; private set; }
public Human(string name, int netId)
{
this.Name = name;
this.NetId = netId;
}
// unlike Java, the entry-point Main method begins with a capital 'M'
public static void Main(string[] args)
{
Human human = new Human("Yoon Lee", 99);
int expected = human.NetId; // parantheses not required for property-getter
}
}
}
You're trying to use a method as if it's a property. You need parenthesis and to convert the string to int, or just make getNetID return an int.
I think you meant:
public int getNetID()
{
return netId;
}
Or better still, use automatic properties:
public int NetId {get; private set;} //Notice Making N in Net capital
And then:
int expected = human.getNetID();
This will do the trick (-:
It should be human.getNetID()
Edit: And yes, as Oren says - you should change your netId getter to return int. I assume that is what you want to do.
I see that netId is integer.
getNetID() return type is string.
return type is not matching.
netID is declared as an Int:
public int netId;
but your function getNetID returns a string:
public String getNetID()
Therefore, the body of getNetID makes no sense when it tried to return an int as a string:
return netId;
Human human = new Human("Yoon Lee", 99);
int expected = human.getNetID(); //<-gets the error at this moment.
you need to add parentheses after the method call.
The way you have it right now you are fetcing the function itself.

Categories

Resources