Lets say we have this example hierarchy:
abstract class Shape { }
class Circle : Shape
{
public int Radius { get; set; }
}
class Rectangle : Shape
{
public int A { get; set; }
public int B { get; set; }
}
I am wondering if it's possible to use pattern matching in C# on a variable of type Shape to determine if it has property Radius e.g.
// Imaginary syntax
if (myShape is { int Radius} )
{
}
I have not found that this is possible, so I assume the answer is no, but probably someone knows better.
Alternatives that I can think of:
Enumerate all the known scenarios (i.e. of Type Circle, etc.), downside is that an introduction of a new type in the future will break it
Introducing an interface, which might be cumbersome depending on the scenario
Using reflection (not too nice)
Related
I have the following scenario:
/* Attribute to be filled */
public class Flower
{
public FlowerType Type { get; set; }
public string Value { get; set; }
}
public enum FlowerType
{
Rose,
Daisy,
Tulip
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class FlowerAttribute : Attribute
{
public string FlowerValue { get; }
public FlowerAttribute(string flowerValue)
{
FlowerValue = flowerValue;
}
}
What I am trying to achieve is a way to give the class Flower an attribute depending on runtime, meaning that if the flower will be instantiated as a Rose type, then the attribute on top of Flower will have the FlowerValue set to "Rose". Can I achieve this somehow? Thanks as always in advance!
Can I achieve this somehow?
No. Attribute arguments are always decided at compile-time - that's why they have to be compile-time constants. The values are baked into the IL.
It's not clear what the bigger goal is here, but anything dynamic is unlikely to be a good fit for attributes.
Below is an example of what I am trying to do.
public class Map{
int id;
int type;
List<Points>;
}
public class Points{
int xpos;
int ypos;
int id;
//Building bg; or Parking pg;
}
public Building{}
public Parking{}
Now according to the type attribute in Map class I need to add either Building or Parking class object into Points Class.
Eg: If type == 1 then add Building to Points else if type == 2 add Parking to Points.
Could anyone please help me with this ?
A way to do it, is to make both Building and Parking inherit from Point (I'd recommend a better name by the way, maybe Location).
public class Location
{
public int Id { get; }
public int X { get; }
public int Y { get; }
}
public class Building : Location
{
public int Stories { get; }
}
public class Parking: Location
{
public int Capacity { get; }
}
And now, your List<Location> inside Map can handle both buildings and parkings:
locations.Add(someBuilding);
locations.Add(someParking);
Another option is to use interfaces: interface ILocation that will be implemented by Building and Parking and a List<ILocation> in Map.
When to use one or another depends on what the commonality between the different types really is:
Inheritance: A derived type is a base class, A dog is an animal.
Interfaces: A type implementing an interface behaves like the interface. An int behaves like an IEquatable<int>, a string too. Is there anything in common between string and int besides this behavior?
I created this interface:
public interface IPhrase
{
int CategoryId { get; set; }
string PhraseId { get; set; }
string English { get; set; }
string Romaji { get; set; }
string Kana { get; set; }
string Kanji { get; set; }
}
and this class:
public class Phrase : IPhrase
{
public Phrase()
{
}
public int CategoryId { get; set; }
public string PhraseId { get; set; }
public string English { get; set; }
public string Romaji { get; set; }
public string Kana { get; set; }
public string Kanji { get; set; }
}
Here this code returns data and typecasts it to Phrase:
var phrases = db2.Query<Phrase>("SELECT * FROM Phrase", ans);
var phrases = db2.Query<IPhrase>("SELECT * FROM Phrase", ans);
What I would like to know is if there is any difference / advantage in my using the IPhrase here or Phrase? Also what advantages are there (if any) in my creating a IPhrase interface in this example. Does that lead to more readable code?
An interface is a contract that guarantees, any class implementing the interface will implement the methods and properties defined in the interface. This allows you to use the interface to create methods, lists, etc. which accept any class that implements the interface e.g.
public interface IExample
{
int GetInt();
}
public void ProcessInt(IExample value)
{
var tempInt = value.GetInt();
// Do processing here
}
This allows any concrete class that implements interface IExample to be passed to this method. The method is assured that any concrete class passed will have the method GetInt implemented.
With objects you can inherit from to things:
Other Objects
Interfaces
Object
If you have an Animal object, a Dog object can inherit from it as it is an animal.
With Object inheritance think of the phrase: I am a ...._yourObject_...
Interface
With an interface you can think of it as a describer for that object. Such as IWalkOnTwoLegs or ICanSwim.
So think of the phrase : I can do ...._yourInterface_..
Now to answer your question, would it make a difference if you use an interface or not?
Well, it wouldn't in this case but if you extend your phrases and create a Question object and a Statement object, for example, and they inherit from Phrase, you have a choice where you can return all phrases (questions and statements) or only phrases that are Questions or only Statements.
You can also apply an interface saying IAmInFrench and IAmInSpanish to your phrase so you can have extended SpanishPhrase and FrenchPhrase objects.
Now you can return either all phrases whether they are questions, statements, in a different language, or you can be specific and return only french phases.
Where I find interfaces are most useful are for registration of different types in unity.
Where it will make a difference:
Where it will definitely make a difference is if there is a property on the object that isn't on the interface, then if you return the interface you will not be able to access that property very easily unless you type cast.
eg:
public class Phrase : IPhrase
{
public Phrase()
{
}
public int CategoryId { get; set; }
public string PhraseId { get; set; }
public string English { get; set; }
}
And interface
public interface IPhrase
{
int CategoryId { get; set; }
}
You will not be able to access the property English if you return the interface:
var phrases = db2.Query<IPhrase>("SELECT * FROM Phrase", ans);
var eng = phrases[0].English; //**THIS WONT WORK**
There is no difference between using an interface and a concrete object locally, as in your example. The main difference is when you are sending interfaces vs concrete classes as parameters in APIs or constructors parameters, where is preferably using interfaces so you can achieve decouple and testability.
Still for your question the short answer is no, there is no difference, whether you want to use interfaces or concrete objects as local variables is your own choice (what seems more readable to you). Do not forget that fields and properties are good to be declared as interfaces which provides more flexibility.
One last thing which should be considered when using a concrete object instead of an interface even locally is that you may want someday to change the signature of the method which provides you that object to return another kind of object which implements the same interface, and in that case you should change the local variable too (even if it's not so bad and it happens very rarely I had to note it), as in the following example:
interface IAnimal
{
void Run();
}
class Cat : IAnimal
{
public void Run()
{
//...
}
}
class Dog : IAnimal
{
public void Run()
{
//...
}
}
If in your code you have a method which returns a Cat that you use:
Cat GetAnimal()
{
return new Cat();
}
Cat myAnimal = GetAnimal(); //note that here it is expected a Cat
myAnimal.Run();
Then if you change the GetAnimal signature to return a Dog, your code should be changed in order to compile to:
Dog myAnimal = GetAnimal(); //note that here it is expected a Cat
myAnimal.Run();
But if you are using an interface there are less chances that your code will need to be changed when method's signatures ar changed:
IAnimal myAnimal = GetAnimal(); //this is working whether a Cat or a Dog is received.
myAnimal.Run();
But again this is happening relatively rarely. Sorry for the silly Cat & Dog example!
A class is a template for an object. It is essentially a blueprint. So for a light there a button that is on and off. Say when you call this method a value is sent to some controller that turns it on and off. All you have to do is call the method for on/off and viola it works.
An interface is very similar. Here the on/off method might not be implemented. You actually have to go and write the code to turn the light on and off but you must write the on/off method or it cannot be that interface. Say there is a new type of light that has dimming functionality. An interface allows you to implement this new feature for a different type of light. So its basically telling you that you have to have this stuff done (on/off) for it to be a light but we don't care how you implement it. Some parts of the interface may be implemented for you, but other parts you have to implement.
When would an interface make sense? A situation where you have many objects that are very similar in nature but differ slightly in implementation. For example say you have many types of shapes. Each is going to have an area. The calculation is different for a triangle than it is for a circle. Now say you have hundreds of shapes that need to be constructed, you wouldn't keep making new objects for each type of shape, you would just implement the interface. This gives somebody the power to create shapes, maybe even custom shapes, with similar methods but different implementations.
Your answer depends on the way you want to use your future classes. Interfaces are contracts to ensure descendant classes have all definitions of interface. So This is useful when you want to use polymorphism. in this way, you can define all common specifications of an object in an interface class. Another advantage of interfaces is that your class can inherit from multiple interfaces, which is not allowed for other type of classes in C#. Here is an example code. Hope to be useful for you:
public interface IShape
{
float Area { get; }
float circumference { get; }
}
public class Rectangle : IShape
{
private float l, h;
public Rectangle( float length, float height ) { l = length; h = height; }
public float Area { get { return l * h; } }
public float circumference { get { return ( l + h ) * 2; } }
}
public class Circle : IShape
{
private float r;
public Circle( float radius ) { r = radius; }
public float Area { get { return (float)Math.PI * r * r; } }
public float circumference { get { return (float)Math.PI * r * 2; } }
}
public class SomeClass
{
IShape[] shapes = new IShape[] // Can store all shapes regardless of its type
{
new Rectangle( 10f, 20f ),
new Rectangle( 15f, 20f ),
new Rectangle( 11.6f, .8f ),
new Circle( 11f ),
new Circle( 4.7f )
};
public void PrintAreas()
{
foreach ( var sh in shapes )
Console.WriteLine( sh.Area ); // prints area of shape regardless of its type
}
public void PrintCircumference(IShape shape )
{
Console.WriteLine( shape.circumference ); // again its not important what is your shape, you cant use this function to print its cicumference
}
}
I am trying to learn better programming practices using SOLID principles. Here I am working on a sample application of Shapes. I just want to know, am I breaking the principle anywhere.Below are classes and its code.
1. Base Class - Shape
public abstract class Shape
{
public abstract double Area();
public virtual double Volume()
{
throw new NotImplementedException("You cannot determine volume from here...Method not implemented.");
}
}
2. Classes for Shapes like Rectangle, Triangle etc implementing base class Shape.
public class Circle : Shape
{
public int Radius { get; set; }
public override double Area() { return 3.14 * Radius * Radius; }
}
public class Triangle : Shape
{
public int Height { get; set; }
public int Base { get; set; }
public override double Area()
{
return 0.5 * Base * Height;
}
}
public class Rectangle : Shape
{
public int Length { get; set; }
public int Breadth { get; set; }
public override double Area()
{
return Length * Breadth;
}
}
public class Square : Shape
{
public Square() { }
public int Side { get; set; }
public override double Area()
{
return Side * Side;
}
}
3. A factory class that returns Shape.
internal class ShapeFactory<K, T> where T : class, K, new()
{
static K k;
private ShapeFactory() { }
public static K Create()
{
k = new T();
return k;
}
}
Till here everything seems fine and looks good, but problem occurs when I implemented it. I am little confused here. Lets see the front end code first:
internal class Program
{
private static void Main(string[] args)
{
try
{
var c = ShapeFactory<Shape, Circle>.Create();
// this part is not clear to me. See the questions below
if(c is Circle)
{
var circle = c as Circle;
circle.Radius = 5;
Console.WriteLine(string.Format("{0}", circle.Area()));
}
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex.Message);
}
Console.Read();
}
}
QUESTIONS
Different shapes has got different properties like circle has Radius, triangle has base and height and so on , so i decided to keep my properties in child class. I knew, I can have that as virtual member in my base class. So Is there any way other than coded above.
If not, then what is the use of abstract class, if still I am typecasting my Shape object to circle object? I can simple use Circle c = new Circle(). I don't want unwanted checks like (if c is circle) and all.
What If , I am asked to implement a new method to get Circumference of a circle. Do I need to create a new Abstract class or put it in Circle class. But if I put it Circle, I think it will break very first principle of SOLID i.e. SRP
.
Kindly note, I don't my abstract class as a fat class having unnecessary or repeated properties.
Thanks in advance
What I usually do in this case is to pass constructor parameters in concrete classes. So i'd change your concrete shapes to something like:
public class Circle : Shape
{
public int Radius { get; set; }
public Circle(int radius) {
this.Radius = radius;
}
public override double Area() { return 3.14 * this.Radius * this.Radius; }
}
public class Rectangle : Shape
{
public int Length { get; set; }
public int Breadth { get; set; }
public Rectangle(int lenght, int breadth) {
this.Length = lenght;
this.Breadth = breadth;
}
public override double Area()
{
return Length * Breadth;
}
}
and so on
Now, I would use a factory method, so your fabric will now be like:
public abstract class ShapeFactory
{
abstract Create();
}
public class CircleFactory : ShapeFactory
{
private int radius;
public CircleFactory(int radius){
this.radius = radius;
}
protected override Shape Create()
{
return new Circle(this.radius);
}
}
public class RectangleFactory : ShapeFactory
{
private int length;
private int breadth;
public RectangleFactory(int length, int breadth){
this.lenght = length;
this.breadth = breadth;
}
protected override Shape Create()
{
return new Rectangle(this.length, this.breadth);
}
}
Notice that, now a factory know how to build a shape with constructor passed in its own constructor.
So, each time you want a diferent shape you will instantiate a new factory.
ShapeFactory factory = new CircleFactory(5);
Shape shape = factory.Create();
Console.WriteLine(shape.Area()));
I think this answer your 1st and 2nd question.
So, 3:
What you can do to dont modify your class is use the strategy pattern in order to pass at runtime how to implement this method:
public interface IPerimeter
{
int calculatePerimeter();
}
public class Circunference : IPerimeter
{
public int calculatePerimeter(Circle circle) {
return 2*pi*circle.radius;
}
}
public class Circle : Shape
{
public int Radius { get; set; }
private IPerimeter perimeter;
public Circle(int radius, IPerimeter perimeter) {
this.Radius = radius;
this.perimeter = perimeter;
}
public Circunference() {
perimeter.calculatePerimeter(this);
}
public override double Area() { return 3.14 * this.Radius * this.Radius; }
}
Hope this helps with your training.
Different child classes will have different properties, that's expected and ok. Normally not all derived classes have the exact same properties as their base class. There's no reason to force Shape to have a Radius. What advantage would you have? That's just opening the door for trouble. What's your ultimate goal with this? Having something like myShape.Dimension = value and not care if it's a radius, a side, etc.? Anything can be done, depending on your needs.
With your abstract class you can, for example, loop through a list of Shape and call Area() or Volume(), knowing that you will get your result (despite your still not implemented Volume). Also your base class could have some common code, which in this case you are not using. You could have for example a Unit property which could be cm, inches, meters, etc. and then have a method like this (silly example):
public string GetAreaString()
{
return string.Format("{0} {1}", this.Area().ToString(), this.Unit);
}
Just implement it in Circle, of course. Why would it break Circle's single responsibility? Your class is dealing with the calculation of its
related values, just like a string tells you if it's null or its length.
For me your example seems really over engineered. I think you should always implement the simplest thing that works nothing more nothing less. I know that this is an example code, because you want to learn the SOLID principles, but I think is important to be aware of how horribly wrong can go these principles in the wrong context. In your specific code: do you need to group all your shapes using the Shape class? I mean, do you ever plan to iterate through a list of Shapes and calculate the area and volume for them? If not, the inheritance has absolutely no point. In fact I would say that inheritance is overused these days, and when it is overused you end up with ugly inheritance dependency graphs. Regarding the factory class: Is construction of any of your "shape" objects particularly difficult, time consuming, tricky. Does your factory class provide some value or it is completely useless? In case it has no real reason to exist, I wouldn't use it, the new operator is far more clear.
I hope you don't mind my reply but I just wanted you to be aware of the fact that some SOLID principles applies in very specific scenarios. Forcing them in the wrong places may cause ugly and over complicated code. In some real world situations, if the questions above are answered with yes, your pattern seems OK. Otherwise the exact same pattern can over-complicate things without any real benefits. I guess my point is: just be aware, not every SOLID principle is good in any situation:).
This is extremely common problem. While learning SOLID is nice, it requires understanding of basic design principles like abstraction and indirection. The reason why you are confused is because there is no abstraction in your code.
Imagine you have code that wants to know shape's area, but it doesn't care what shape it is nor how to calculate that shape's area. Something like :
public void PrintArea(Shape shape)
{
Console.WriteLine(shape.Area());
}
This is THE CRITICAL PART of OOP design. Your example has absolutely nothing of this. Your example is just contrived piece of code that has no logic to it, let alone being SOLID.
I am creating a class library that will be used to create other applications with specific functionality. The library should implement all of the concrete functionality, and the implementing application will add specific business rules to the classes. Typically this is a trivial representation of some objects:
In class library:
interface IWheel
{
int Radius { get; set; }
string Color { get; set; }
}
abstract class Wheel : IWheel
{
int Radius { get; set; }
string Color { get; set; }
}
interface ICar
{
string Color { get; set; }
List<IWheel> Wheels { get; set; }
}
abstract class Car : ICar
{
string Color { get; set; }
List<IWheel> Wheels { get; set; }
public Car()
{
List<IWheel> Wheels = new List<IWheel>();
}
}
In implementing application business logic:
class SpecialWheel : Wheel
{
int SpecialWheelProperty { get; set; }
}
class SpecialCar : Car
{
string SpecialCarProperty { get; set; }
}
In implementing application instantiation:
SpecialWheel wheel1 = new SpecialWheel { SpecialWheelProperty = 6 };
SpecialWheel wheel2 = new SpecialWheel { SpecialWheelProperty = 6 };
SpecialWheel wheel3 = new SpecialWheel { SpecialWheelProperty = 8 };
SpecialWheel wheel4 = new SpecialWheel { SpecialWheelProperty = 8 };
SpecialCar car = new SpecialCar();
car.Wheels.Add(wheel1);
car.Wheels.Add(wheel2);
car.Wheels.Add(wheel3);
car.Wheels.Add(wheel4);
All is good so far, until I try to do something like:
// Cant do this as "SpecialWheelProperty" is not in the Interface contract
int wheelSpecialProperty = car.Wheels.First().SpecialWheelProperty;
I could of course add the "SpecialWheelProperty" to the IWheel Interface and make it an abstract property of the Wheel class, but this would defeat my final objective of implementing the business logic in derived classes.
I have a few ideas floating round in my head (maybe generics), but, in this case what is the best approach, and an example of that approach?
The problem is that your code expresses no relationship between the SpecialCar and SpecialWheel classes, yet expects the interface of SpecialCar to expose SpecialWheel instances. The fact that you're actually adding all SpecialWheel instances is entirely coincidental.
This seems like a task for generics, with the base class accepting a type parameter implementing IWheel.
abstract class Car<TWheel> : ICar where TWheel : IWheel
{
string Color { get; set; }
ICollection<TWheel> Wheels { get; set; }
public Car()
{
Wheels = new List<TWheel>();
}
}
class SpecialCar : Car<SpecialWheel> {
// Whatever
}
Now you can still do this without losing any type safety:
int swp = car.Wheels.First().SpecialWheelProperty;
A word of caution: while this technique makes your desired code possible, it can quickly grow out of control if used in deep class hierarchies. Please use sparingly.
So far as I understand a
SpecialWheel
Is on the business logic so that appears to be normal to cast to get it specific properties:
int wheelSpecialProperty = (car.Wheels.First() as SpecialWheel).SpecialWheelProperty;
A question: why do you create a constructor in
Car
Since it is abstract?
I think, it will be hard to answer this question in one precise way. The problem is to understand your system. Here you only have what I called a "technique". In this case an inheritance and polymorphism. But when you build system, it is usually more than this. You may have a framework, plumbing if you like, where all operations are done on interface level. Factories. Then, in specialized areas, you have business-specific code like this:
class CarFactory
{
public static ICar BuildCar(int kind);
if (int == 0)
return new RegularCar();
else
return new SpecialCar();
}
so in your "Special" code you can add special property value
SpecialCar sc = (SpecialCar)CarFactory.BuildCar(1); // notice casting
sc.SpecialProperty = "special value";
So, only specific clients/consumers will know about special properties. Your application will operate with
ICar, IWheel, // etc
for example, when you acquire regular car, your client has no idea about 1, only 0.
RegularCar rc = (RegularCar)CarFactory.BuildCar(0); // notice casting
But the handler that calls "AddWheels" has no idea of what car it is and declared as
CarBuilderWheelHandler.AddWheels(ICar c, List<IWheel> w)
CarBuilderWheelHandler may need to mount tires, inflate and balance each of them. But your special wheel may have installed Tire pressure monitoring system rather than regular valve. In this case your special car has a device to monitor TPMS and knows how to handle special wheel properties. But when it flows from handler to handler, those handlers don't know the specifics of "special" things. Hadlers work with interfaces.
void AddWheels(ICar c, List<IWheel> w)
{
MountRubber(w);
Inflate(w);
Balance(w);
c.Wheels = w;
}
Then somewhere inside special car, it knows how to monitor pressure
void Timer_Tick(...)
{
foreach(SpecialWheel w in _wheels)
{
if w.Pressure < _pressureSetByDriver //'Pressure' is not part of IWheel
SendPressureWarningToDashboard();
}
}
This is really abstract example, may be only good for you to understand what is purpose of Abstract objects in OOP.
I believe that your question can have many answers and we don't have exact context under which you working