I'm new to C# and have no idea why doesn't it work. I'm trying to create 3 methods that create a new Vehicle object with different properties. I've tried to do it with polymorphism but it's been even worse. I bet the answer to that is so easy..
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace PetrolStation
{
class Program
{
static void Main(string[] args)
{
Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(DisplayTimeEvent);
aTimer.Interval = 1000; // 1000=1s
aTimer.Enabled = true;
Console.ReadLine();
void DisplayTimeEvent(object source, ElapsedEventArgs e)
{
Random rand = new Random();
int temp = rand.Next(1, 3);
if (temp == 2)
{
Vehicles vehicle = new Vehicles();
vehicle.newCar();
Console.Out.WriteLine("test", vehicle.carType); // it should print "car" after test but it doesn't
}
if (temp == 3)
{
Vehicles vehicle = new Vehicles();
vehicle.newVan();
Console.Out.WriteLine("test", vehicle.carType);// it should print "van" after test but it doesn't
}
}
}
}
Second class:
public class Vehicles
{
public string carType;
public string fuelType;
public int tankCap;
public double fuelInTank;
public Random rand = new Random();
public void newCar()
{
carType = "Car";
tankCap = 40;
fuelInTank = rand.NextDouble() * 10;
int tempFuelType = rand.Next(1, 3);
switch (tempFuelType)
{
case 1:
fuelType = "petrol";
break;
case 2:
fuelType = "Diesel";
break;
case 3:
fuelType = "LPG";
break;
}
}
public void newVan()
{
carType = "van";
tankCap = 80;
fuelInTank = rand.NextDouble() * 20;
int tempFuelType = rand.Next(1, 2);
if (tempFuelType == 1)
{
fuelType = "Diesel";
}
else
{
fuelType = "LPG";
}
}
using System;
namespace StackOverflow_OOP
{
class Program
{
// Randomness removed: you want a driver to **consistently** pass or fail.
static void Main(string[] args)
{
Car car = new Car(VehicleFuelType.Petrol, 20);
// The first arg specifies format/placement of the second
Console.Out.WriteLine("Vehicle Type: {0}", car.Type);
// In background, uses String.Format()
// See https://msdn.microsoft.com/en-us/library/system.string.format(v=vs.110).aspx
Van van = new Van(VehicleFuelType.Diesel, 40);
Console.Out.WriteLine("Vehicle Type: {0}", van.Type);
Console.ReadLine();
}
}
// A string that only takes a small number of values is called an enumeration
// See https://msdn.microsoft.com/en-us/library/sbbt4032.aspx
public enum VehicleFuelType
{
Petrol,
Diesel,
LPG
}
// Vehicle is clearly abstract in this context, while Car & Van are concrete.
// See explaination after code.
public abstract class Vehicle
{
public VehicleFuelType FuelType { get; }
public int TankCap { get; }
public double FuelInTank { get; private set; }
public string Type { get { return this.GetType().Name; } }
public Vehicle(VehicleFuelType fuelType, int tankCap, double fuelInTank)
{
FuelType = fuelType;
TankCap = tankCap;
FuelInTank = fuelInTank;
}
}
public class Car : Vehicle
{
public Car(VehicleFuelType fuelType, double fuelInTank) : base(fuelType, 40, fuelInTank)
{
}
}
public class Van : Vehicle
{
public Van(VehicleFuelType fuelType, double fuelInTank) : base(fuelType, 80, fuelInTank)
{
}
}
}
Classes: Abstract vs. Concrete
public abstract class Shape
{
public abstract double GetArea();
}
public class Circle : Shape
{
public int Radius { get; }
public Circle(int radius)
{
Radius = radius;
}
public override double GetArea()
{
return Math.PI * Radius * Radius;
}
}
public class Square : Shape
{
public int SideLength { get; }
public Square(int sideLength)
{
SideLength = sideLength;
}
public override double GetArea()
{
return SideLength * SideLength;
}
}
The simplest difference between an abstract class and a concrete one:
An abstract class cannot be instantiated (directly); a concrete one can.
For instance,
Shape shape = new Shape(); // impossible
Circle circle = new Circle(); // fine
Crucially,
Shape circle = new Circle(); // fine
Conceptually, it's impossible to create an abstract class (e.g. shape) without actually creating a concrete class (circle).
Even more simply, imagine going to a restaurant and telling the waiter you want "food". Obviously he can comply, but somewhere along the line "food" must become steak or tuna or spaghetti, etc.
Regarding the direct problem you mentioned:
The problem is related to the WriteLine call.
The signature of the call you mane
Console.Out.WriteLine("test", vehicle.carType);
is
public virtual void WriteLine(string format, object arg0)
So the first parameter in this call should have an item which you want to composite (see https://msdn.microsoft.com/en-us/library/system.string.format(v=vs.110).aspx for more details).
bottom line the call should be something like
Console.Out.WriteLine("test {0}", vehicle.carType);
Regarding the "polymorphism" you mentioned:
What you implemented isn't polymorphism.
You might want to read about polymorphism a little bit:
oop: https://msdn.microsoft.com/en-us/library/mt656686.aspx
polymorphism: https://msdn.microsoft.com/en-us/library/ms173152.aspx
Related
I have read a lot of things about how marker interfaces are bad (or not, it does not seem so clear).
I do not really understand how Marker Attributes work, and I have created a small example to illustrate my issues:
I have an interface to define Robot, and an other one to define Ninja. It turns out that it exists a classFoo that can multiply stuff, but only with the help of someone which is both a RobotAND a Ninja.
using System;
public class Program
{
public static void Main()
{
IRobotNinja robotNinja = new RobotNinjaAlways10();
Foo foo = new Foo();
Console.WriteLine(foo.Multiply(1, 1, robotNinja));
}
}
public class Foo
{
public int Multiply(int leftOperand, int rightOperand, IRobotNinja robotNinja)
{
return leftOperand * rightOperand * robotNinja.availableShuriken * robotNinja.batteryLevel;
}
}
public interface IRobot
{
int batteryLevel
{
get;
}
}
public interface INinja
{
int availableShuriken
{
get;
}
}
public interface IRobotNinja : IRobot, INinja
{
}
public class RobotNinjaAlways10 : IRobotNinja
{
public int batteryLevel
{
get
{
return 10;
}
}
public int availableShuriken
{
get
{
return 10;
}
}
}
It is my understanding that IRobotNinja is a marker class: it has no members.
How can I get the same thing (and in particular, ensuring at compile time that only a Robot/Ninja will help with the Multiply?
To avoid creating another interface, you can make Multiply generic with constraints:
public class Foo
{
public int Multiply<T>(int leftOperand, int rightOperand, T robotNinja)
where T : IRobot, INinja
{
return leftOperand * rightOperand * robotNinja.availableShuriken
* robotNinja.batteryLevel;
}
}
I'm trying to implement a script evaluator to evaluate some classes that my users will implement that will have a fixed entry point accepting a variable that will be given from the main application.
To do this I've declared a namespace that contains the type of the object that will be passed to the entry point. This is the whole code that declares the custom type and executes the scripts:
namespace MyNamespace
{
public class Vertex
{
public float X { get; } = 0.0f;
public float Y { get; } = 0.0f;
public float Z { get; } = 0.0f;
public Vertex(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
public override string ToString()
{
return string.Format("[{0}, {1}, {2}]", X, Y, Z);
}
}
}
public class Globals
{
public Vertex testVertex = new Vertex(0, 0, 0);
public int testValue = 100;
}
class Program
{
static void Main(string[] args)
{
try
{
ScriptOptions options = ScriptOptions.Default;
// Add assemblies
options = options.AddReferences(
typeof(System.Object).GetTypeInfo().Assembly,
typeof(System.Linq.Enumerable).GetTypeInfo().Assembly,
typeof(MyNamespace.Vertex).GetTypeInfo().Assembly
);
// Add usings
options = options.AddImports("System");
options = options.AddImports("System.Linq");
options = options.AddImports("System.Collections.Generic");
options = options.AddImports("MyNamespace");
var script = <added below>;
Globals globals = new Globals();
ScriptState<object> scriptState = CSharpScript.RunAsync(script, options: options, globals: globals).Result;
scriptState = scriptState.ContinueWithAsync(#"Figure fig = new Figure();").Result;
scriptState = scriptState.ContinueWithAsync(#"fig.Draw(testVertex);").Result;
}
catch (CompilationErrorException e)
{
Console.WriteLine(string.Join(Environment.NewLine, e.Diagnostics));
}
}
}
And this is an example of a script that I'm trying to load:
public class Figure
{
public void Draw(Vertex v)
{
System.Console.WriteLine(v.ToString());
}
public void Draw(int i)
{
System.Console.WriteLine(i);
}
}
Now, the problem is that when I call the method Draw of the class Figure inside the script, it throws me an exception saying
error CS1503: Argument 1: cannot convert from 'MyNamespace.Vertex [~/Projects/ScriptTest/ScriptTest/bin/Debug/netcoreapp1.0/ScriptTest.dll]' to 'MyNamespace.Vertex [ScriptTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]'
When I do
scriptState = scriptState.ContinueWithAsync(#"fig.Draw(testValue);").Result; // Using testValue instead of testVertex
everything works fine.
It think the problem is that the script is referring to a different namespace than MyNamespace but I don't know how to solve this.
I am trying to implement the Decorator pattern, but I keep getting an error when I try to compile my program. I cannot figure out why. I know it has something to with something not being an interface, but I have tried a bunch of changes and nothing is working. I appreciate any assistance!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OODAssignment3_ZackDavidson
{
class Program
{
static void Main(string[] args)
{
//Creates a new Calvin Klein Shirt fordecoration
CalvinKlein ckShirt = new CalvinKlein();
Console.WriteLine(Convert.ToString(ckShirt.GetBrand()));
//Puts a solid color on the Calvin Klein Shirt
solidColorDecorator ckSCD = new solidColorDecorator(ckShirt);
//Puts stripes on the Calvin Klein Shirt
stripedShirtDecorator ckSSD = new stripedShirtDecorator(ckShirt);
//Puts a pocket on the Clavin Klein Shirt
pocketShirtDecorator ckPSD = new pocketShirtDecorator(ckShirt);
//Creates a new Tommy Hilfiger Shirt
TommyHilfiger thShirt = new TommyHilfiger();
//Puts stripes on the Tommy Hilfiger Shirt
stripedShirtDecorator thSSD = new stripedShirtDecorator(thShirt);
//Puts a pocket on the Tommy Hilfiger Shirt
pocketShirtDecorator thPSD = new pocketShirtDecorator(thShirt);
}//EndOfMain
}//EndOfClassProgram
public abstract class ShirtsComponent
{
public abstract string GetBrand();
public abstract double GetPrice();
}
class CalvinKlein : ShirtsComponent
{
private string ck_Brand = "Calvin Klein";
private double ck_Price = 75.0;
public override string GetBrand()
{
return ck_Brand;
}
public override double GetPrice()
{
return ck_Price;
}
}
class TommyHilfiger : ShirtsComponent
{
private string th_Brand = "Tommy Hilfiger";
private double th_price = 85.0;
public override string GetBrand()
{
return th_Brand;
}
public override double GetPrice()
{
return th_price;
}
}
public abstract class Decorator : ShirtsComponent
{
ShirtsComponent fashion_Base = null;
protected string _brand = "Undefined Decorator";
protected double _price = 0.0;
protected Decorator(ShirtsComponent fashionBase)
{
fashion_Base = fashionBase;
}
#region ShirtsComponent Members
string ShirtsComponent.GetBrand()
{
return string.Format("{0}, {1}", fashion_Base.GetBrand(), _brand);
}
double ShirtsComponent.GetPrice()
{
return _price + fashion_Base.GetPrice();
}
#endregion
}
class solidColorDecorator : Decorator
{
public solidColorDecorator(ShirtsComponent fashionBase)
: base(fashionBase)
{
this._brand = "Solid Color Shirt";
this._price = 25.0;
}
}
class stripedShirtDecorator : Decorator
{
public stripedShirtDecorator(ShirtsComponent fashionBase)
: base(fashionBase)
{
this._brand = "Striped Shirt";
this._price = 50.0;
}
}
class pocketShirtDecorator : Decorator
{
public pocketShirtDecorator(ShirtsComponent fashionBase)
: base(fashionBase)
{
this._brand = "Dotted Shirt";
this._price = 90.0;
}
}
}//EndOfNamespace
This code is the problem:
#region ShirtsComponent Members
string ShirtsComponent.GetBrand()
{
return string.Format("{0}, {1}", fashion_Base.GetBrand(), _brand);
}
double ShirtsComponent.GetPrice()
{
return _price + fashion_Base.GetPrice();
}
#endregion
You don't need to specify the base class in the method declarations. This is the correct code:
#region ShirtsComponent Members
public override string GetBrand()
{
return string.Format("{0}, {1}", fashion_Base.GetBrand(), _brand);
}
public override double GetPrice()
{
return _price + fashion_Base.GetPrice();
}
#endregion
I'm not at all new to programming, but there seems to be a hole in my understanding of C# structs.
Can anyone explain why the following code prints out the following?
Dist1: 0, Dist2: 0
struct Distance
{
public void SetFeet(int feet) { Value = feet; }
public void SetMiles(float miles) { Value = (int)(miles * 5280f); }
public int GetFeet() { return Value; }
public float GetMiles() { return Value / 5280f; }
private int Value;
}
class Distances
{
public Distance Dist1 { get; set; }
public Distance Dist2 { get; set; }
}
class Program
{
static void Main(string[] args)
{
Distances distances = new Distances();
distances.Dist1.SetFeet(1000);
distances.Dist2.SetFeet(2000);
Console.WriteLine("Dist1: {0}, Dist2: {1}",
distances.Dist1.GetMiles(),
distances.Dist2.GetMiles());
Console.ReadLine();
}
}
Getters and setters -- how properties are accessed -- still function like methods in this regard. That is,
distances.Dist1.SetFeet(1000);
is "equivalent" to
distances.GetDist1().SetFeet(1000);
The "copy" of the structure (value) is made when it is returned from the getter (or passed to the setter). If Dist1 were a member variable this would not be the case and would work "as expected".
Happy coding.
struct are value types - so when you are accessing distances.Dist1.SetFeet you basically are accessing a copy... see for example at MSDN http://msdn.microsoft.com/en-us/library/aa288471%28v=vs.71%29.aspx
[EDIT after comment]
On the other hand, if you do distances.Dist1 = new Distance ().SetFeet (1000); AND change the return of SetFeet from void to Distance it should work. Alternatively make Distance a class.
For a reference on how to build structs in a way that they work as expected see the DateTime struct in the framework - http://msdn.microsoft.com/en-us/library/system.datetime.aspx
[/EDIT after comment]
Properties are treated differently to variables, just remove { get; set; } from your Distance declaration and the code works fine.
struct Distance
{
public void SetFeet(int feet) { Value = feet; }
public void SetMiles(float miles) { Value = (int)(miles * 5280f); }
public int GetFeet() { return Value; }
public float GetMiles() { return Value / 5280f; }
private int Value;
}
class Distances
{
public Distance Dist1;//here
public Distance Dist2;//and here
}
class Program
{
static void Main(string[] args)
{
Distances distances = new Distances();
distances.Dist1.SetFeet(1000);
distances.Dist2.SetFeet(2000);
Console.WriteLine("Dist1: {0}, Dist2: {1}", distances.Dist1.GetMiles(),
distances.Dist2.GetMiles());
Console.ReadLine();
}
}
Create public class in C# such that following conditions are satisfied :
The class cannot be instantiated.
A function from that class can be called by other class.
I tried this way :
public abstract class A {
public static void fun()
{
// do process.
}
}
public class B : A
{
// Now A can't be instantiated being abstract.
// And you can call its function like this :
A.fun();
}
But my answer was wrong.So, please help me out.
You can create a class like as follows to meet your goal
public class A
{
private A()
{
}
public static A GetA()
{
return new A();
}
public void Foo()
{}
}
public class B
{
public void Foo2()
{
A a = A.GetA();
a.Foo();
}
}
Making the constructor of A private would bar it from instantiating from another class. And the static method GetA will return an object of A instatiating it privately which you can use from any class.
you can use static class if you don't like allow to instantiate it use static class, The best sample for it is Math class, Also if you want to have a single instance you can use singleton.
MSDN sample:
public static class TemperatureConverter
{
public static double CelsiusToFahrenheit(string temperatureCelsius)
{
// Convert argument to double for calculations.
double celsius = System.Double.Parse(temperatureCelsius);
// Convert Celsius to Fahrenheit.
double fahrenheit = (celsius * 9 / 5) + 32;
return fahrenheit;
}
public static double FahrenheitToCelsius(string temperatureFahrenheit)
{
// Convert argument to double for calculations.
double fahrenheit = System.Double.Parse(temperatureFahrenheit);
// Convert Fahrenheit to Celsius.
double celsius = (fahrenheit - 32) * 5 / 9;
return celsius;
}
}
class TestTemperatureConverter
{
static void Main()
{
System.Console.WriteLine("Please select the convertor direction");
System.Console.WriteLine("1. From Celsius to Fahrenheit.");
System.Console.WriteLine("2. From Fahrenheit to Celsius.");
System.Console.Write(":");
string selection = System.Console.ReadLine();
double F, C = 0;
switch (selection)
{
case "1":
System.Console.Write("Please enter the Celsius temperature: ");
F = TemperatureConverter.CelsiusToFahrenheit(System.Console.ReadLine());
System.Console.WriteLine("Temperature in Fahrenheit: {0:F2}", F);
break;
case "2":
System.Console.Write("Please enter the Fahrenheit temperature: ");
C = TemperatureConverter.FahrenheitToCelsius(System.Console.ReadLine());
System.Console.WriteLine("Temperature in Celsius: {0:F2}", C);
break;
default:
System.Console.WriteLine("Please select a convertor.");
break;
}
}
}
And for creating class singleton do this:
public sealed class MyClass
{
MyClass()
{
}
public static MyClass Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly MyClass instance = new MyClass();
}
}