Interface vs. concrete object return value question - c#

So I am trying to understand this sample code from Lynda.com without explanation.
IScore.cs
internal interface IScore
{
float Score { get; set; }
float MaximumScore { get; set; }
}
ScoreEntity.cs
internal class ScoreEntity : IScore
{
public float Score { get; set; }
public float MaximumScore { get;set;}
}
ScoreUtility.cs
internal class ScoreUtility
{
public static IScore BestOfTwo(IScore as1, IScore as2)
{
var score1 = as1.Score / as1.MaximumScore;
var score2 = as2.Score / as2.MaximumScore;
if (score1 > score2)
return as1;
else
return as2;
}
}
Calling code:
var ret = ScoreUtility.BestOfTwo(new ScoreEntity() { Score = 10, MaximumScore= 4},
new ScoreEntity() {Score = 10, MaximumScore = 6});
return;
My question is, in the ScoreUtility, what's really the benefit of using the interface type as return type in the method and argument type in the parameters, vs. just using ScoreEntity for the return and parameters, since the method itself returns a concrete object? Is this just to make the code looked 'smart'?

Any class that implements the IScore interface can be passed into the ScoreUtility method.
Perhaps there's a reason to implement another ScoreEntity class, like wanting to add a name seen in NamedScoreEntity :
internal class NamedScoreEntity: IScore
{
public string Name { get; set; }
public float Score { get; set; }
public float MaximumScore { get;set;}
}
If that's the case, then you can still use your utility methods on the new classes because of the contract the IScore interface enforces.
In this case, you could now compare the score between an un-named score object to a score object that also has a name.
Similarly, returning IScore allows the method to remain flexible enough to be used on multiple object types, and you can easily cast the returned type when you need to.

Given this declaration
public static IScore BestOfTwo(IScore as1, IScore as2)
The method does not know (or care) about the concrete types of as1 and as2. They may be ScoreEntity, or may be something entirely different. All it knows is that they implement IScore.
So if the method was to return a concrete type, then you have effectively limited the as1 and as2 parameters to being ScoreEntity, and have reduced its flexibility.
The only way you could guarantee that the method wouldn't fail would be to rewrite it as
public static ScoreEntity BestOfTwo(ScoreEntity as1, ScoreEntity as2)

In the posted code there is very little benefit, and I would argue that the interface should be removed. I would also argue that the comparison logic probably should be part of the object, or possibly an implementation of IComparer<T>.
Interfaces are most useful when there is a good reason for having multiple implementations. IComparer<T> is a great example, you might want to compare scores by the absolute score value, or the relative. So providing an abstraction is really useful.
Just applying interfaces to all classes is not a good idea, it will just make your code more complicated without any benefit. You might also discover that it can be difficult to provide a second implementation if the interface is not designed at the right abstraction level. This may result in adding properties or methods to objects that does not do anything or throws, just because they are required by a implemented interface. See for example IList<T> where many of the implementer throw exceptions for some of the methods.
In the specific case of IScore, it may be useful if you have some need for additional score-classes. But in many cases I would argue that composition might be more useful, i.e.
public class MyNamedScore{
public string Name {get;}
public ScoreEntity Score {get;}
}

Related

Refactoring an interface exposing several possible behaviors but only one can be ever called per instantiation context

Sorry for the lenghty post. I tried to show my attempts and thought process as much as possible.
I got an interface exposing several possible behavior, but there is only one implementation of this interface that is instantiated and only one of the exposed method that can be called in each context where the interface is realized.
This interface will be used in very different context of an application and I wish to avoid exposing method that can't be called.
I wish to find a way so that the caller of IRescheduler would only know one behavior despite different method signatures. I'll detail and example and what I tried so far
public interface IRescheduler
{
AmountByTimeInterval RescheduleTomorrow(Amount amount);
AmountByTimeInterval RescheduleAtGivenDate(Amount amount, DateTime rescheduleDate);
// there will probably be more date strategies in the future
}
AmountByTimeInterval contains an Amount and a TimeInterval associates a string with a timespan from the current date. For example "1Day" would be the timespan from tomorrow to tomorrow and "1Year" would starts a year from now and ends a year later.
public class AmountByTimeInterval
{
public Amount Amount { get; private set; }
public TimeInterval TimeInterval { get; private set; }
public AmountByTimeInterval(Amount amount, TimeInterval timeInterval)
{
Amount = amount;
TimeInterval = timeInterval;
}
}
public class Amount
{
public double Value { get; private set; }
public string Currency { get; private set; }
public Amount(double amount, string currency)
{
Value = amount;
Currency = currency;
}
}
public class TimeInterval
{
public string Name { get; private set; }
public DateTime StartDate { get; private set; }
public DateTime EndDate { get; private set; }
public TimeInterval(string name, DateTime startDate, DateTime endDate)
{
Name = name;
StartDate = startDate;
EndDate = endDate;
}
}
For the sake of this example, let's suppose an IRescheduleAmountCalculator interface that takes Amount to make other Amount
public interface IRescheduleAmountCalculator
{
Amount ComputeRescheduleAmount(Amount amount);
}
Here is an example implementation of my IRescheduler interface. I got a repository pattern that gets me the TimeInterval associated to the DateTime.
public interface ITimeIntervalRepository
{
TimeInterval GetTimeIntervalByName(string name);
TimeInterval GetTimeIntervalByDate(DateTime date);
}
public class Rescheduler : IRescheduler
{
private const string _1Day = "1Day";
private readonly ITimeIntervalRepository _timeIntervalRepository;
private readonly TimeInterval _tomorrow;
private readonly IRescheduleAmountCalculator _calculator;
public Rescheduler (ITimeIntervalRepository timeIntervalRepository, IRescheduleAmountCalculator calculator)
{
_calculator = calculator;
_timeIntervalRepository = timeIntervalRepository;
_tomorrow = timeIntervalRepository.GetTimeIntervalByName(_1Day);
}
public BucketAmount RescheduleTomorrow(Amount amount)
{
Amount rescheduledAmount = _calculator.ComputeRescheduleAmount(amount);
return new TimeInterval(_tomorrow, transformedAmount);
}
public AmountByTimeInterval RescheduleAtGivenDate(Amount amount, DateTime reschedulingDate)
{
TimeInterval timeInterval = _timeIntervalRepository.GetTimeIntervalByDate(reschedulingDate);
Amount rescheduledAmount = _calculator.ComputeRescheduleAmount(amount);
return new TimeInterval(timeInterval, transformedAmount);
}
}
I don't know beforehand the context in which IRescheduler would be called, it is meant to be used by many components. Here is an abstract class I intend to provide and an example of specific implementation
public abstract class AbstractReschedule<TInput, TOutput>
{
private readonly ITransformMapper<TInput, TOutput> _mapper;
protected readonly IRescheduler Rescheduler;
protected AbstractReschedule(IMapper<TInput, TOutput> mapper, IRescheduler rescheduler)
{
_mapper = mapper;
Rescheduler = rescheduler;
}
public abstract TOutput Reschedule(TInput entityToReschedule);
protected TOutput MapRescheduledEntity(TInput input, TimeInterval timeInterval)
{
return _mapper.Map(input, timeInterval);
}
}
public class RescheduleImpl : AbstractReschedule<InputImpl, OutputImpl>
{
public RescheduleImpl(IRescheduleMapper<InputImpl, OutputImpl> mapper, IRescheduler rescheduler) : base(mapper, rescheduler)
{
}
public override OutputImpl Reschedule(InputImpl entityToReschedule)
{
AmountByTimeInterval rescheduledAmountByTimeInterval = Rescheduler.RescheduleTomorrow(entityToReschedule.AmountByTimeInterval.Amount);
return Map(entityToReschedule, rescheduledAmountByTimeInterval);
}
}
public interface IMapper<T, TDto>
{
TDto Map(T input, AmountByTimeInterval amountByTimeInterval);
}
Forcing an interface on TInput generic parameter is out of question, as the component is meant to be used in a large number of bounded contexts. Each future user of this whole rescheduling component would implement its own implementation of AbstractReschedule and IMapper.
I tried a strategy pattern but the different method argument blocked me as I couldn't define an interface contract that would allow all behaviour without exposing the actual implementation of IRescheduler.
Then I implemented a visitor pattern, where IRescheduler would have an Accept method and an implementation by behavior :
public interface IRescheduler
{
AmountByTimeInterval Accept(IReschedulerVisitor visitor, Amount amount);
}
public class RescheduleTomorrow : IRescheduler
{
public AmountByTimeInterval Accept(IReschedulerVisitor visitor, Amount amount)
{
return visitor.Visit(this, amount);
}
}
public class RescheduleAtGivenDate : IRescheduler
{
public AmountByTimeInterval Accept(IReschedulerVisitor visitor, Amount amount)
{
return visitor.Visit(this, amount);
}
}
As you noticed, the DateTime is not present here, because I actually inject it in the visitor, which is built by a Factory
public interface IReschedulerVisitor
{
AmountByTimeInterval Visit(RescheduleTomorrow rescheduleTomorrow, Amount amount);
AmountByTimeInterval Visit(RescheduleAtGivenDate rescheduleAtGivenDate, Amount amount);
}
public class ReschedulerVisitor : IReschedulerVisitor
{
private readonly ITimeIntervalRepository _timeIntervalRepository;
private readonly DateTime _chosenReschedulingDate;
private readonly IRescheduleAmountCalculator _rescheduleAmountCalculator;
private const string _1D = "1D";
public ReschedulerVisitor(ITimeIntervalRepository timeIntervalRepository, IRescheduleAmountCalculator rescheduleAmountCalculator)
{
_timeIntervalRepository = timeIntervalRepository;
_rescheduleAmountCalculator = rescheduleAmountCalculator
}
public ReschedulerVisitor(ITimeIntervalRepository timeIntervalRepository, IRescheduleAmountCalculator rescheduleAmountCalculator, DateTime chosenReschedulingDate)
{
_timeIntervalRepository = timeIntervalRepository;
_chosenReschedulingDate = chosenReschedulingDate;
_rescheduleAmountCalculator = rescheduleAmountCalculator
}
public AmountByTimeInterval Visit(RescheduleTomorrow rescheduleTomorrow, Amount amount)
{
TimeInterval reschedulingTimeInterval = _timeIntervalRepository.GetTimeIntervalByName(_1D);
Amount rescheduledAmount = _rescheduleAmountCalculator(amount);
return new AmountByTimeInterval(reschedulingTimeInterval, rescheduledAmount);
}
public AmountByTimeInterval Visit(RescheduleAtGivenDate rescheduleAtGivenDate, Amount amount)
{
TimeInterval reschedulingTimeInterval = _timeIntervalRepository.GetTimeIntervalByDate(_chosenReschedulingDate);
Amount rescheduledAmount = _rescheduleAmountCalculator(amount);
return new AmountByTimeInterval(reschedulingTimeInterval, rescheduledAmount);
}
}
public interface IRescheduleVisitorFactory
{
IRescheduleVisitor CreateVisitor();
IRescheduleVisitor CreateVisitor(DateTime reschedulingDate);
}
public class RescheduleVisitorFactory : IRescheduleVisitorFactory
{
private readonly ITimeIntervalRepository _timeIntervalRepository;
public RescheduleVisitorFactory(ITimeIntervalRepository timeIntervalRepository)
{
_timeIntervalRepository = timeIntervalRepository;
}
public IRescheduleVisitor CreateVisitor()
{
return new RescheduleVisitor(_timeIntervalRepository);
}
public IRescheduleVisitor CreateVisitor(DateTime reschedulingDate)
{
return new RescheduleVisitor(_timeIntervalRepository, reschedulingDate);
}
}
Finally (sorry for lengthy post), the RescheduleImpl that every user would have to implement would become like this :
public class RescheduleImpl : AbstractReschedule<InputImpl, OutputImpl>
{
public RescheduleImpl(IRescheduler rescheduler, IRescheduleVisitorFactory visitorFactory, IRescheduleMapper<InputImpl, OutputImpl> mapper)
: base(cancel, visitorFactory, mapper) {}
public override OutputImpl Reschedule(InputImpl entityToReschedule)
{
AmountByTimeInterval rescheduledAmountByTimeInterval = rescheduler.Accept(visitorFactory.CreateVisitor(), entityToReschedule.AmountByTimeInterval.Amount);
// the second case would be :
// AmountByTimeInterval rescheduledAmountByTimeInterval = rescheduler.Accept(visitorFactory.CreateVisitor(entityToReschedule.Date), entityToReschedule.AmountByTimeInterval.Amount);
return Mapper.Map(entityToReschedule, rescheduledAmountByTimeInterval);
}
}
While this works, I'm quite unhappy with the solution. I feel like the implementer of my solution would decide of the rescheduling strategy twice. The first time when chosing the implementation of IRescheduler to use build the last RescheduleImpl class I showed, and a second time when deciding which method of the factory to call.
I'm currently out of ideas and open to any that could solve the original problem. I'm also open to totally different implementation than my visitor + factory attempt.
Thank you for taking the time to read or answer my problem.
I think the fundamental reason why this has gotten so complicated is this:
I got an interface exposing several possible behavior, but there is only one implementation of this interface that is instantiated and only one of the exposed method that can be called in each context where the interface is realized.
Here's a way of rephrasing that:
I need different behaviors in different contexts, but I want them to all be in one interface.
The answer is not to do that. If you need one behavior here and a different behavior there, it's better to define one interface for the behavior you need here and another for what you need there.
This relates to the Interface Segregation Principle. Roughly it says that we shouldn't have one class depend on an interface but only use some if its members. When a class depends on an interface, that interface should only contain what the class needs.
If you put all of these behaviors in one interface, then it's likely to be implemented in one big class. And then every time you need another behavior, you add it to that interface, which means the class that implements it has to change. If that one class is used (to do entirely different things) by lots of other classes, then every change to the one class has potential to affect the others.
Or you might get part of the way through and realize that you want to re-architect this. You might see some way to simplify or improve. But then the same thing happens. Lots of classes depend on this interface for different reasons, so now your one change impacts lots of classes.
Or, in plainer terms: I wrote this class. I use parts of it in ten other classes. The next class I want to use it with needs something slightly different. So to meet the needs of one class, I'm going to modify the interface (and implementation) that ten other classes depend on. That might mean having to change all those classes, and I shouldn't have to change ten classes because of one. Or the change might accidentally break the other ten classes.
Those are ripple effects, and the ISP helps us to minimize them so that changing one thing doesn't affect or make us change other things.
If there are distinct behaviors and different classes need different ones, then it's better to "segregate" those interfaces, giving each class only what it needs. One way to accomplish that is to define each interface from the perspective of the class or classes that need them.
Sometimes we might try to pile more into one class so that the different types of behaviors can share some functionality or code, but there are other ways to accomplish that. If we find that two of these implementations need something similar or identical then we can just that duplicated part into a separate class and then both implementations depend on that.
Another reason why that approach is helpful is because it leads us to only write the code we need right now. Then as we write one, two, three classes, we might discover the commonalities and opportunities for reuse and refactor. That goes much more smoothly than if we try to plan for that commonality up front, write code based on that, and then once we start using it in other classes we discover that it wasn't what we needed.
#ScottHannen is correct that the problem relates to interface segregation. You are lucky that you have current requirements that demonstrate the problem right now, instead of finding out later and having to change a whole lot of deployed code.
But identifying the violated SOLID principle is not the same as fixing the problem, and I think you need a more practical answer, so:
Since different contexts can require different services from the reschedulers they use, you shouldn't try to force all reschedulers to use the same interface. You have identified two different kinds right now, but there's no reason there can't be more later.
Now, you may be thinking that you should split your IRescheduler into INextDayRescheduler and IFutureRescheduler, or whatever, and leave room for arbitrary others later on, BUT an arbitrary interface provides no value, so what this really means is that you should remove the requirement for the IRescheduler interface, since there is really no such interface at all.
You consume this interface in the AbstractReschedule constructor, but AbstractReschedule doesn't use it. So just stop that. Remove the constructor argument or (if you're omitted important code) take a different interface that gives it just what it needs.
With this one change, implementors of AbstractReschedule can just do it however they want and your problem is solved.
If there are many implementors that could use an INextDayRescheduler, or whatever, then go ahead and make a some handy utility classes that can make those common use cases easier to handle, but always bear in mind that these are utility classes that clients can chose to use, or not, according to their whims, instead of being requirements of your API.

Generic interfaces with abstract implementations

I am trying to implement some graph searching algorithms in .NET for fun and personal education. For my implementation, I chose to start with a Node class that implemented the following interface:
public interface INode<T>
{
T Data { get; }
IDictionary<INode<T>, int> Neighbors { get; set; }
}
The node contains some Data of type T, as well as a dictionary of nodes that it shares an edge with along with their integer distance. I then thought that I could create an abstract Node class:
public abstract class Node<T> : INode<T>
{
public T Data { get; private set; }
public IDictionary<INode<T>, int> Neighbors { get; private set; }
public Node(T data, IDictionary<Node<T>, int> neighbors)
{
this.Data = data;
this.Neighbors = neighbors;
}
}
The above doesn't work, however, since neighbors doesn't match Neighbors. I would like whatever parameters are in Node's constructor to include an IDictionary of that specific type of Node and not just something that implements INode. For example, I might later create a concrete class called GraphNode, and I want to be sure that only GraphNodes are used in the constructor.
To solve this, I could simply take the IDictionary Neighbors out of INode and put it into the abstract Node class. This could limit my ability to test the class later on though using a framework like FakeItEasy, and I'm not sure what other implications it might have down the line.
I would appreciate some suggestions on how to generally approach this problem. If there is no best solution, then what are some pros and cons of various solutions?
Based on the given code, there are two things that you can do to make this compile.
First, the code also doesn't compile because INode<T> is not fully implemented. Your interface defines a set method for Neighbors, so your set will have to be public, or you will have to explicitly implement that property.
Second, presuming you really want to restrict your constructor to take neighbors as a dictionary keyed on the Node<T> class, and not the interface, the quickest thing you can do to load up this.Neighbors is change the line to
this.Neighbors = neighbors.ToDictionary(
neighborDistance => (INode<T>)neighborDistance.Key,
neighborDistance => neighborDistance.Value
);
Something like this must be done because generic IDictionary is not covariant.

How to mimic static override?

Every time I want to make something like a "static override" (which is not possible in C#) I find questions that say this is caused by a poor design. How would you design your code to avoid this?
Example: some game with lots of units, each has a different cost (an int or something like that), but each of the subclassses has the same cost. It would make sense here(IMHO) using an "abstract static", but that is not possible. Which is the best way to model this cases?
I usually end up creating an abstract method that returns a static variable that I have to create (and remember!) in each subclass, but then I always depend on having an instance of each class, any other ideas?
No need to use statics here at all. Simply define a base class for all concrete units, that takes the cost as initialization argument:
public abstract class UnitBase
{
public int Cost { get; private set; }
public UnitBase(int cost)
{
this.Cost = cost;
}
}
Taking this as the base for your inheritance tree, you would then go along these lines:
public abstract class Unit1Base : UnitBase
{
public Unit1() : base(<actual_cost>) { }
}
public class ConcreteUnit1 : Unit1Base {}
public class ConcreteUnit2 : Unit1Base {}
This way, each concrete unit will have the desired cost value...
but each of the subclassses has the same cost.
That seems like a good candidate for a base class containing a Cost property that the others will inherit:
public virtual decimal Cost
{
get { return 20m; }
}
Then if anywhere down the chain you have some other price, you could override the Cost property.
You are correct in that you cannot have a static virtual/override property. This can be annoying for the case you describe, which I too have struggled with in the past.
However, you can use static properties... and the new keyword to hide the base implementation.
For example, let's define some units here:
public abstract class BaseUnit
{
public static int UnitCost { get { return 10; } }
}
public class CheapUnit : BaseUnit
{
new public static int UnitCost { get { return 5; } }
}
public class ExpensiveUnit : BaseUnit
{
new public static int UnitCost { get { return 20; } }
}
public class MultipleUnit : BaseUnit
{
new public static int UnitCost { get { return BaseUnit.UnitCost * 4; } }
}
Then a little test program to output their values:
public void Run()
{
Console.WriteLine("Base unit cost:\t\t{0}", BaseUnit.UnitCost);
Console.WriteLine("Cheap unit cost:\t{0}", CheapUnit.UnitCost);
Console.WriteLine("Expensive unit cost:\t{0}", ExpensiveUnit.UnitCost);
Console.WriteLine("Multiple unit cost:\t{0}", MultipleUnit.UnitCost);
}
And we get...
Base unit cost: 10
Cheap unit cost: 5
Expensive unit cost: 20
Multiple unit cost: 40
Ah ha! Exactly what we want. I'm not 100% happy with this solution but I don't know a better way without having to create an instance which I think it silly to access a polymorphic class constant. So I just do it this way.
EDIT: In cases where I found myself doing this, I often opted to move this kind of 'lookup' logic into a manager (singleton) class. For example, UnitManager or similar, where I could pass in a type name ("CheapUnit") and it would look up the cost in a Dictionary.
Just a quick mockup idea:
sealed class UnitManager
{
static readonly UnitManager instance = new UnitManager();
public static UnitManager Instance { get { return instance; } }
Dictionary<string, int> unitCostDictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); // Ignore Case of Keys
public int LookupUnitCost(string unitType)
{
int unitCost = 0;
unitCostDictionary.TryGetValue(unitType, out unitCost);
return unitCost;
}
}
This also allows dynamic unit cost and centralized notifications when a unit cost may change.
Create a Factory class (static) that returns the instance you want but have the declaration of the factory method return the abstract type?
While I sometimes miss the ability to override a static method in .net, it wouldn't be for this scenario.
Aside from simply using inheritance which you seem to be dead against for some reason I can't fathom, another way to do it might be, to delegate cost to one static class which took unit type as an argument.
Another would be to make cost an attribute of the class and look it up via reflection.

Best way to separate read and write concerns using interfaces?

Lately I've been realizing the benefit of (some would argue overuse of) immutable objects to cut down dramatically on read-write dependency issues in my object model and their resulting conditions and side-effects, to ultimately make the code simpler to manage (kind of functional-programming-esque).
This practice has led me to create read-only objects that are provided values at creation/construction time and then to make available only public getters for external callers to access the properties with. Protected, internal and private setters allow internal control to be maintained over writing to the object model.
When creating interfaces while making an API over my object model, I've started considering the same issues about immutability. For example, by providing only public getters on my interfaces, and leaving it up to implementors to decide upon setters and how to handle that aspect.
An example of a "read-only" interface for implementation that I'm talking about is this Valuable Item (just for demonstration):
public interface IValuableItem {
decimal Amount {get;}
string Currency {get;}
}
However I got to wondering how I should provide a companion interface that allows for writing (and if I should), and not combine those operations within the same interface as to not "taint" its immutability.
The following ideas have come to mind, just off the top of my head. Without providing what I think are pros and cons to each, what do you think the best approach is? Is there a coding methodology common in the industry for managing this concept?
// companion writer
public interface IValuableModifier {
decimal Amount {set;}
string Currency {set;}
}
or
// explicit methods to enforce importance of or deviance in the programming
public interface IValuableModifier {
void SetAmount(decimal val);
void SetCurrency(string cur);
}
or
// companion writer that inherits the original interface
public interface IValuableModifier : IValuableItem { //...
or
// Let a concrete class choose one and/or the other.
class Concrete : IValuableModifer, IValuableItem { //...
or
etc...
What else can help me imbue writing on my otherwise immutable programming model and keep it moderately flexible or at least to separate the concerns for better control over it?
I think I might use a variant of your ideas, something like this:
public interface IValuableItem
{
decimal Amount { get; }
string Currency { get; }
}
public interface IMutableValuable : IValuableItem
{
new decimal Amount { set; get; }
new string Currency { set; get; }
}
class Item : IMutableValuable
{
public decimal Amount { get; set; }
public string Currency { get; set; }
}
This way your mutable interface has full getters and setters (I don't think it makes sense to have an interface that has setters but no getters), but any object that implements it will also have an immutable version of the interface that you can use for any pure-functional code.
You should have separate interfaces for ReadableFoo, ImmutableFoo, and MutableFoo. The latter two should inherit from the first. ReadableFoo should contain an "AsImmutable" method which will return a Foo that is guaranteed to be immutable (a immutable instance should return itself; a mutable instances should return a new immutable instance which contains its data), and probably an "AsNewMutable" member (which will create a new mutable instance containing the same data, whether the original was mutable or not).
No class should implement both ImmutableFoo and MutableFoo.
If your objects are to be immutable (and you design your application around the concept of immutable data) then objects really MUST remain immutable.
The canonical method for modifying data in immutable scenarios is to create new objects, so I would suggest something like this:
public interface IValuableItem<T>
{
decimal Amount { get; }
string Currency { get; }
T CreateCopy(decimal amount, string currency);
}
public class SomeImmutableObject : IValuableItem<SomeImmutableObject>
{
public decimal Amount { get; private set; }
public string Currency { get; private set; }
public SomeImmutableObject(decimal amount, string currency)
{
Amount = amount;
Currency = currency;
}
public SomeImmutableObject CreateCopy(decimal amount, string currency)
{
return new SomeImmutableObject(amount, currency);
}
}
SomeImmutableObject obj = new SomeImmutableObject(123.33m, "GBP");
SomeImmutableObject newObj = obj.CreateCopy(120m, obj.Currency);
Consider using a builder pattern: Builder objects construct immutable instances of the core object. .NET Strings are like this - the string object is immutable, and there is a StringBuilder class for efficient construction of string objects. (string + string + string is much less efficient than using a StringBuilder to do the same)
Note also that builder objects exist solely for building the target object - builders are not instances of the target object / do not implement the target interface themselves.
It's worth the effort to make your system run on immutable objects, as immutability washes away a lot of headaches in threading / concurrency / parallel execution scenarios, as well as data caching / data versioning scenarios.
I believe combining your 3rd and 4th choice is a better way to implement mutable & immutable types.
Public interface ImmutableItem {
decimal Amount {get;}
string Currency {get;}
}
Public interface MutableItem: ImmutableItem {
decimal Amount {set;}
string Currency {set;}
}
class Concrete : ImmutableItem {
//Only getters
}
class Concrete : MutableItem {
//Both getters & setters
}
This is clean and it let the concrete classes to decide which kind of mutability is wanted to expose to outer world.

How can I implement an interface that can take many object types

excuse what seems like a real noobie question but how can I implement the following
public interface IViewModel {
void Map<T>();
}
public class CarViewModel : IViewModel
{
public string Color { get; private set; }
public int Tyres { get; private set; }
public CarViewModel(Car _car)
}
//this is where the problem is - there can be many differnt kind of object but I want them all to implement a Map function. I want to be able to assign the properties to incoming object. I also need to cater for IList of cars coming in that need to be populated. I suspect I am not using Generics properly
public void Map<T>(Car _car){
Color = _car.Color;
Tyres = _car.Tyres;
}
Do you mean this?
public interface IViewModel<T>
{
void Map(T domainObject);
}
public class CarViewModel : IViewModel<Car>
{
public Map(Car domainObject) { ... }
}
You say:
I suspect I am not using Generics properly
and you are correct. Additionally, you are not using polymorphism properly.
If you want to polymorphically accept several different types that all have something in common, then you need to create an interface that is the parent type of all of the types you will be using. You can do this without using any Generics at all.
What Generics (aka parametric polymorphism) gives you is a way to create one type that is parameterized by another type (and thus behaves like many different types). For example, IList<T> is parameterized by a type variable T -- then IList<string> and IList<int> are two separate types (with many possible subtypes each), but you only have to write the code once.
What are your actual requirements for this design? What are your ViewModel classes trying to accomplish?

Categories

Resources