Proper way to enforce business rules in property setter - c#

Let's say an application has an Employer object has been created by a user and the program is prompting the user to enter in a property called EmployerId. In this example the application won't let the user enter in an invalid EmployeeId. I have mocked up the following solution to solve the problem.
public int EmployerId
{
get { return employerId; }
set
{
EmployerId = SetEmployerId();
}
}
public int SetEmployerId()
{
int id = 0;
Console.Write("Enter employer ID: ");
id = Convert.ToInt32(Console.ReadLine());
while (id < 5 || id > 10) //silly logic for illustrative purposes
{
Console.Write("Invalid id, enter another id: ");
id = Convert.ToInt32(Console.ReadLine());
}
return this.employerId = id;
}
this keeps any heavy lifting out of the setter of the property and delegates that responsibility to the SetEmployerId method.
Would this be an acceptable solution in a production setting? Is there any way this could be improved upon, or any pitfalls this might lead to later down the road when the application isn't such a contrived example? (besides the fact that the user isn't aware of what valid input is).

I think the better question is should an outside class be able to modify EmployerId directly.
Most often times methods that create mutation should exposed as verbs so something like ChangeEmployer(Employer newEmployer) and so on. Doing it that way make it more explicit and allows you to more easily raise domain events. In this case the set method would be private so that only the owning class can call it.
That said, any change of EmployerId should be verified in the setter that way the logic is only in one place and not strewn about multiple methods.
Karl Anderson's answer makes a very good point, that putting business logic in a setter like that prevents returning a non-exceptional error. This is true and should be taken into consideration before using property setters.
He also makes a good point about validation objects, your aggregate entities may only reference each other by Id as such having a separate business validation object for validating those Ids may be an excellent choice. You can reuse the validator in multiple places but at the end of the day the only place that matters is inside the entity, as that is the only place that must always be consistent.
public class Employee
{
private EmployerId employerId;
public Employee(EmployerId id /* other params such as name etc */)
{
var employerSetResult = this.SetEmployerId(id);
if(!result.Success)
throw new ArgumentException("id", "id is invalid");
}
// this is a separate method because you will need to set employerId
// from multiple locations and should only ever call SetEmployerId
// internally
public Result ChangeEmployer(EmployerId id)
{
var result = this.SetEmployerId(id);
if(result.Success)
DomainEventPublisher.Publish(
new EmployeeEmployerChanged(id, this.id));
return result;
}
private Result SetEmployerId(Employer id)
{
var result = EmployerIdValidator.Validate(id);
if(result.Success)
this.employerId = id;
return result;
}
}
public static class EmployerIdValidator
{
public static Result Validate(EmployerId id)
{
if(id < 5)
return new Result(success: false, new ValidationResult("Id too low"));
else if (id > 10)
return new Result(success: false, new ValidationResult("Id too high"));
return new Result(success:true);
}
}
public class Result
{
public bool Success {get {return this.success;}}
public IEnumerable<ValidationResult> ValidationResults
{
get{ return this.validationResults; }
}
}

One of the downsides of your approach is the inability to return "error" information about why the business rule failed. In your example you are directing output to the Console, which does the calling code no good.
I would recommend building a set of business rule classes that can be applied to your business objects and then processed upon an event (i.e. the presentation layer calls Validate on the business object) and then a collection (i.e. List<string> of errors) can be returned and used by the calling code (i.e. presentation layer).

I like approaches that Karl and Mgetz talked about.
Just wanted that if you want to use setters and getters and to separate your bussiness logic from presentation you doomed to use Exceptions and your code coud look like this:
public class WrongEmployeeIDException : Exception
{
public WrongEmployeeIDException(string message) : base(message) { }
}
public class Employee
{
private int employerId;
public int EmployerId
{
get { return employerId; }
set
{
if (value < 5 || value > 10)
{
throw new WrongEmployeeIDException("Invalid id");
}
employerId = value;
}
}
}
public void Main()
{
int id;
string input;
bool isSetted = false;
Employee employee = new Employee();
while (!isSetted)
{
Console.Write("Enter employer ID: ");
try
{
input = Console.ReadLine();
id = Convert.ToInt32(input);
employee.EmployerId = id;
isSetted = true;
}
catch (WrongEmployeeIDException ex)
{
Console.WriteLine(ex.Message);
//not satisfied to bussiness rules
}
catch (FormatException ex)
{
Console.WriteLine(ex.Message);
//Convert.ToInt32 thrown exception
}
catch
{
//something more bad happend
}
}
}
But it's not recommended aproach because validation logic will execute more smoothly and faster with Magetz's solution. It's something middle between your solusion and Magetz's.

Related

c# Return string of Customer name

I am new to C# and trying to solve some simple tasks and I find my self stuck in a methode that is supposed to get the name of the next customer from right on the list:
The task:
I am given is a directed graph of Customers, where one Customer has exactly one reference to the next Customer or null if it is the last Customer. An example of such a graph can be seen in the diagram below.
Given such a graph, I need to find the customer int numberFromRight nodes from right in the graph by implementing the IFinder interface.
Here is the code I have been working on
class Program
{
static void Main(string[] args)
{
var currentCustomer = Customers
.Create("Kim")
.Previous("Hans")
.Previous("Ole")
.Previous("Peter");
while (currentCustomer != null)
{
if (currentCustomer.Next != null)
Console.Write(currentCustomer.Person + " -> ");
else
Console.WriteLine(currentCustomer.Person);
currentCustomer = currentCustomer.Next;
}
Console.ReadLine();
}
}
Customer class
public class Customers
{
private Customers(Customers next, string person)
{
Next = next;
Person = person;
}
public Customers Next { get; }
public string Person { get; }
public Customers Previous(string person)
{
return new Customers(this, person);
}
public static Customers Create(string person)
{
return new Customers(null, person);
}
}
IFinder interface
public interface IFinder
{
string FromRight(Customers customers, int numberFromRight);
}
I want to write my answer in this method and in example is in the graph below the result for FromRight(peter, 3) is Ole.:
public class Finder : IFinder
{
public string FromRight(Customers customers, int numberFromRight)
{
return name;
}
}
Simple solution without recursion:
public class Finder : IFinder
{
public string FromRight(Customers customers, int numberFromRight)
{
return Unwind(customers).Reverse().Skip(numberFromRight - 1).FirstOrDefault()?.Person;
}
private static IEnumerable<Customers> Unwind(Customers customers)
{
while (customers != null)
{
yield return customers;
customers = customers.Next;
}
}
}
The task: I am given is a directed graph of Customers, where one Customer has exactly one reference to the next Customer or null if it is the last Customer.
So basically what you have in memory is a linked list. While they have some advantages, they are pretty rarely used outside of tree structures exactly because they are a pain to itterate or random access over.
I want to write my answer in this methode and in example is in the
graph below the result for FromRight(peter, 3) is Ole.:
This is recursion, with the number being the recursion depth. Something like this:
public string FromRight(Customers customers, int numberFromRight)
{
if(numberFromRight <= 0)
return customers.Name;
else
return FromRight(customer.Next, (numberFromRight-1));
}
I might have a off-by-one error in this. But those buggers are everywhere. And if forget the null check of course. But it should get you into the right direction at least.
You haven't really showed us what you have tried so far here, just giving us the assignment.
So here's the theorical answer :
Use recursion with the following :
if the next customer doesn't exist, you're at the end of the list, therefore you can return a value straight ahead.
if the next customer does exist, then the answer is the next customer's answer plus one.

Generic class to store variable content

I want to create a structure to store data consumed from a Web Service with the followind specs:
Response:
Field 1 - InstructionType: Can be 1 (PreferredDay), 2 (SVP), 3 (Neighbour)
Field 2: Some variable data. Its type depends on Field 1. So if:
Field 1 == 1 then Field 2 type will be of DateTime (dd.MM.yyyy)
Field 1 == 2 then Field 2 type will be of type string.
Field 1 == 3 then Field 2 type will be of type string
So, I started up with the following enum:
public enum InstructionType
{
None = 0,
PreferredDay = 1,
ServicePoint = 2,
Neighbour = 3
}
And the generic class:
public abstract class Instruction<T>
{
public InstructionType Type { get; private set; }
public T Data { get; private set; }
public Instruction(InstructionType type, T data)
{
this.Type = type;
this.Data = data;
}
}
and concrete classes:
public class PreferredDayInstruction : Instruction<DateTime>
{
public PreferredDayInstruction(DateTime data)
: base (InstructionType.PreferredDay, data) {}
}
public class ServicePointInstruction: Instruction<string>
{
public ServicePointInstruction(string data)
: base (InstructionType.ServicePoint, data) {}
}
public class NeughbourInstruction: Instruction<string>
{
public NeughbourInstruction(string data)
: base (InstructionType.Neighbour, data) {}
}
When parsing web service's response created a public function:
public Instruction DeliveryInstruction() <---Compiler error here "Instruction"
{
if (resultFromWebservice.Field1 == 1)
return new PreferredDayInstruction((DateTime)Field2);
if (resultFromWebservice.Field1 == 2)
return new ServicePointInstruction(Field2);
if (resultFromWebservice.Field1 == 3)
return new NeighbourInstruction(Field2);
}
and here is the problem. Can't return objects of generic type.
Tried with with Interface, factories, and other stuff, but allways with the same problem. So, is there any way to archieve this? maybe it's not possible or maybe is so easy I can't see now. Thanks in advance.
UPDATE:
Compiler error on BOLD Instruction
Error 1 Using the generic type 'NAMESPACE.Instruction' requires '1' type arguments
I forgot..I'm using .NET 3.5
It looks like you may be starting off with an intent to use generics rather than using them because you've identified a need. Often (not always) when that gets difficult it's because it didn't actually fit what you were trying to do.
What seems odd in this case is that you have both a generic type and an enum to indicate the type. This is likely to cause you a few problems.
First it looks like you're trying to create a one-size-fits all class to model different types of behaviors. That will start off confusing and get more confusing. Think of most classes that are part of the .NET framework, and imagine what would happen if they had properties like Field1 and Field2, and you couldn't tell from looking at them what they were for. And in one method they're used for one thing, but in a another case they mean something else.
Also, if you're trying to put different types of instructions in one class, that suggests that maybe you're going to try passing them all to one method, and that method figures out what to do, and maybe calls other methods. (I'm guessing that because of the enum. Perhaps you're going to handle the input differently depending on which value it contains.) That one method will get really hard to maintain.
I'd recommend waiting on generics until you're sure you need them. And if you have different types of instructions you're likely better off writing a different class for each one with the properties it needs and names that describe them, and writing methods for each of them to do what they need to do. If you need lots of classes, make lots of them.
It's very easy to fall into the trap of trying to solve problems that don't exist, like how do I write one class that covers a bunch of different needs. The answer usually that you don't need to. You'll get better results from writing more classes that each do fewer things.
Believe me that I tried to do my best to explain what was my problem and what I needed in order to solve it. In a nutshell, the question was quite simple. Is this possible or not? So, is there a way to return a common type for these 3 classes? Answer is no, as they don't share any root. They all derive from Instruction, but aren't compatible each other. That's what I learned from this experience.
As another example, lets take another .NET framework's generic type.
public class ListOfString : List<string> { }
public class ListOfInt : List<int> { }
public class ListOfDecimal : List<decimal> { }
And, in another place of the application, get a method who returns one of this List based on some logic:
public class Logic
{
public List<> GetList(Type t) <----This can't be done
{
if (t == typeof(string))
return new ListOfString();
if (t == typeof(int))
return new ListOfInt();
if (t == typeof(decimal))
return new ListOfDecimal();
else return null;
}
}
Please, keep in mind that this is just a stupid sample just to show what's the point of this post.
By the way, in the case of List the following can be done, because there is a non generic different version of IList:
public IList GetList(Type t)
{
....
}
But I can't think of a way to do this in my particular case.
Anyway, I finally followed another approach. I reallized that what I really wanted is to ensure Data property is valid. If it it's supposed to be a date there, ensure date is valid. Is it a string, ensure it has the right length or whatever rule it must follow.
So this is the final solution:
The enum:
public enum InstructionType
{
None = 0,
PreferredDay = 1,
ServicePoint = 2,
Neighbour = 3
}
The base class:
public abstract class Instruction
{
public InstructionType Type { get; private set; }
public string Data { get; private set; } <---Type String
public Instruction(InstructionType type, string data)
{
this.Type = type;
this.Data = IsValid(data) ? data : string.Empty;
}
public abstract bool IsValid(string data); <--the rule.
}
The concrete classes:
public class PreferredDayInstruction : Instruction
{
public PreferredDayInstruction(string date)
: base(InstructionType.PreferredDay, date) { }
public override bool IsValid(string data)
{
string[] formats = {"dd.MM.yyyy", "d.MM.yyyy",
"dd.MM.yy", "d.MM.yy"};
try
{
data = data.Replace('/', '.').Replace('-', '.');
var dateparts = data.Split('.');
DateTime date = new DateTime(Convert.ToInt32(dateparts[2]),
Convert.ToInt32(dateparts[1]),
Convert.ToInt32(dateparts[0]));
//DateTime.ParseExact(data, formats, null, System.Globalization.DateTimeStyles.AssumeLocal);
return true;
}
catch (Exception)
{
return false;
}
}
}
public class ServicePointInstruction : Instruction
{
public ServicePointInstruction(string data)
: base (InstructionType.ServicePoint, data) { }
public override bool IsValid(string data)
{
return ServicePointBarcodeValidator.Validate(data);
}
}
public class NeighbourInstruction : Instruction
{
public NeighbourInstruction(string data) :
base(InstructionType.Neighbour, data) { }
public override bool IsValid(string data)
{
return data.Length <= 70;
}
}
A factory class, who's responsability is to create and return the correct object based on the enum:
public static class DeliveryInstructionFactory
{
public static Instruction Create(int type, string data)
{
return Create((InstructionType)type, data);
}
public static Instruction Create(InstructionType type, string data)
{
switch (type)
{
case InstructionType.PreferredDay:
return new PreferredDayInstruction(data);
case InstructionType.ServicePoint:
return new ServicePointInstruction(data);
case InstructionType.Neighbour:
return new NeighbourInstruction(data);
default:
return null;
}
}
}
And finally, as now all of they share the same root, object can be created on webservice's response parser:
public Instruction DeliveryInstruction()
{
try
{
int instructionCode = int.Parse(observation.Substring(173,2));
string instructionData = observation.Substring(175, 10);
return DeliveryInstructionFactory.Create(instructionCode, instructionData); }
catch (Exception ex)
{
Log.Error("[ValidationBarcodeResponse] DeliveryInstructions aren't in the correct format", ex);
return null;
}
}
Hope this now fits on a Minimal, Complete, and Verifiable example

method returning same object which was passed as parameter

Is it acceptable practice to pass an object into a method, then return the same object rather than creating a new object inside of the method itself?
As an example: if have an entity class as follows:
class UserDetails {
int UserID { get; set; }
string UserName { get; set; }
string UserAge { get; set; }
}
And then I pass an instance of this class to a method, as follows:
UserDetails UserInfo = new UserDetails();
UserInfo = Get_Details(UserInfo);
Is it reasonable for the method to do the following?
public UserDetails Get_Details(UserDetails user) {
// SQL Operations...
user.age = 32;
return user;
}
IMO, there is no need to return the object. Since it is passed to the method by reference, the caller already has a reference to the same object (with the updated values after the method completes).
On the other hand, what can be useful in some situations is a fluent-interface, where instance-methods of a class return the instance again, e.g:
class X
{
public X DoThis(int number)
{
// do something
return this;
}
public X DoThat(string name)
{
// do something else
return this;
}
}
This allows to write very readable code, such as:
var x = new X().DoThis(23).DoThat("asdf");
This can be useful with the builder pattern (when you want to build a complex object step by step).
As a very bad example:
class FooBuilder {
FooBuilder WithAge(int age);
FooBuilder WithUrl(Url url);
Foo ToFoo();
}
new FooBuilder().WithAge(12).WithUrl(new Url("http://www.happybirthday.com/").ToFoo();
In your particular case, I'd prefer to initialize everything in one go with the initializer syntax.
new User { Age = 45, UserName = "Bob", Id = 101 };
There is nothing horribly wrong with this but a couple of observations;
You are setting details inside of a method called get perhaps load is more appropriate.
If you are only passing in UserDetails because you want the id for your then the parameter should just be id instead. This keeps the interface cohesive.
It is generally considered bad form to modify a parameter object within a method, i.e., mutation principle.
Doing it like that is rather pointless, as the assignment that you do doesn't change anything.
Calling it like this:
UserInfo = Get_Details(UserInfo);
gives the same result as calling it and ignoring the return value:
Get_Details(UserInfo);
Returning the reference may only be confusing, leading someone to believe that the method returns a new instance, as that would be the only logical reason to return a reference.
It would make more sense to have that method in the class, so that you call it as:
UserInfo.Get_Details();
If your method is supposed to initialise the object, you would rather put the code it the constructor than calling it after creating the instance:
class UserDetails {
int UserID { get; set; }
string UserName { get; set; }
string UserAge { get; set; }
public UserDetails() {
Get_Details(this);
}
}
Then you just create the instance, and the constructor loads the data:
UserDetails UserInfo = new UserDetails();
This is a possible approach and when you have only ONE item to work one, the best, too. You might also consider to use ref, which creates a reference to the passed parameter
public void Get_Details(ref UserDetails user)
{
// SQL Operations. . .
user.age= 32;
}
this way, you don't pass a copy, but reference the object you passed in. But this can become quite obscure and is unnecessary in your case. See here for an insight.
You can fill your entity in its constructor method or another method inside entity class. It will be ready to use when created.
public class SomeClass
{
public string Field_1;
public int Field_2;
public SomeClass(int ID)
{
// Sql operations by ID or another value
// set fields
}
public AnotherMethod(int ID)
{
// Sql operations by ID or another value
// set fields
}
}
You might do well to look up the concepts of the Repository Pattern and OOD. In general, I prefer projections or fully loaded entities.
public UserDetailsProjection GetDetailsByUserId(Guid userID)
{
// Code goes here
return user;
}
Note: ref is not required, because all objects are passed by reference.

Multiple accessors for same value in c#

I have simple scenario where I have AnotherTest value based on Test value. This works fine most of the time so that whenever I provide Test I am sure to get AnotherTest easily.
public sealed class Transaction {
public string Test { get;set; }
public string AnotherTest{
get {
int indexLiteryS = Test.IndexOf("S");
return Test.Substring(indexLiteryS, 4);
}
}
}
However I wanted to be able to also set AnotherTest value and be able to read it without having to provide Test value. Is this possible? So kinda 2 types of get based which way it was set. I know I could create 3rdTest but I have some methods that use AnotherTest and other fields and I would have to write overloads of that methods.
Edit:
I read some file supplied by bank. I cut it in pieces put some stuff in Test value and every other field (AnotherTest and similar) of the Transaction gets filled automatically.
However later on I would like to read Transaction from SQL that is already in nice format so I don't need to provide Test to get the rest of the fields. I would like to set those fields with set and then be able to use get without setting Test value.
Yes, like so:
public string Test { get; set; }
public string AnotherTest
{
get
{
if(_anotherTest != null || Test == null)
return _anotherTest;
int indexLiteryS = Test.IndexOf("S")
return Test.Substring(indexLiteryS, 4);
}
set { _anotherTest = value; }
}
private string _anotherTest;
That getter could also be expressed as
return (_anotherTest != null || Test == null)
? _anotherTest
: Test.Substring(Test.IndexOf("S"), 4);
I think this would do what you want it to do:
public sealed class Transaction {
public string Test { get;set; }
public string AnotherTest{
get {
if (_anotherTest != null)
{
return _anotherTest;
}
else
{
int indexLiteryS = Test.IndexOf("S");
return Test.Substring(indexLiteryS, 4);
}
}
set {
_anotherTest = value;
}
}
private string _anotherTest = null;
}
I would suggest turning the problem over.
It sounds like you're dealing with a big field and subfields within it. Instead, how about promoting those subfields to fields and constructing/deconstructing the big field when it's accessed.

Inheriting a Linq to SQL class and cast the result of a linq query

I am writing an application where we will need to extend a basic entity into a number of different things (eg employee, vehicle etc). The design is as such that there is a Entity table and a second table with type specific values eg an employee will have an ID Number but a vehicle will have a registration number.
I have inherited from the class entity generated in the Data Context but am having trouble with the casting in my repository. What is the correct way of doing this?
public class cAccountEmployee : cAccountEntity
{
public string id_number
{
get
{
try
{
return this.cAccountEntityValues.Single(e => e.type == 1).value;
}
catch (Exception)
{
return "";
}
}
set
{
try
{
this.cAccountEntityValues.Single(e => e.type == 1).value = value;
}
catch (Exception)
{
this.cAccountEntityValues.Add(new cAccountEntityValue()
{
accountentity_id = this.id,
cAccountEntity = this,
type = 1,
value = value
});
}
}
}
}
Then in my repository (does not inherit anything)
public IEnumerable<cAccountEmployee> All(int accountholder_id)
{
return db.cAccountEntities.Where(e => e.accountholder_id == accountholder_id).OrderBy(a => a.name).Cast<cAccountEmployee>();
}
public cAccountEmployee Single(int id)
{
return db.cAccountEntities.Single(a => a.id == id) as cAccountEmployee;
}
The cast fails in the single method and hence I get back null. It is my understanding you cannot define explicit or implicit operators from or to a base class? How can I get the base class Linq result to cast up to the inherited Employee class, while still maintaining its db state so I can submit changes?
With LINQ-to-SQL, there are two ways inheritance can work:
discriminator over a single table (not suitable since your data is not homogeneous)
base-class / multi-table (not that this isn't supported in the dbml - only if you write the classes manually)
LINQ-to-SQL does not support multi-table inheritance (i.e. a single object with data from multiple tables). Entity Framework does, but is more complex; you use .Cast<T> and .OfType<T> in EF to cast/filter based on sub-types.
You might want to look at:
querying based on an ID (combine with GetTable<T>())
specifying a base-class in the dbml
What is the purpose of the base class here? If it adds behaviour, then you can edit the dbml to specify a common base-class for all your entities. If it has data properties then it gets trickier.
Personally, I simply wouldn't do it this way... I would keep separate classes for the different types, and use the data-context correctly, using the separate tables per type:
public IEnumerable<Employee> All(int accountholder_id)
{
return db.Employees.Where(e => e.accountholder_id == accountholder_id)
.OrderBy(a => a.name);
}
public Employee Single(int id)
{
return db.Employees.Single(a => a.id == id);
}
So - can you clarify what the cAccountEntity does here?
Thanks for the input, will look over some of the suggestions...
The idea behind account entity was that as of now the site only needs to handle employees but in the future they may want to add vehicles etc to the system, the system is used to assign costs to an entity, so for this purpose an employee is handled the same as a vehicle.
The idea being that an employee and a vehicle need to he handled the same for referencing in the db etc but will need slightly different info about them. It is a complex design only because they want to add extra types later but without needing to upgrade the db...
In my code however I want to talk about an employee not about a generic entity type (make controller, view etc much easier in an mvc app). As you cannot supply a user-defined casting from base to derived class I have skipped inheritting it and used the following solution instead. Bit more cumbersome but does work... Let me know if someone can see a better way of doing this.
public class cAccountEmployee
{
private cAccountEntity entity;
public int id
{
get
{
return this.entity.id;
}
set
{
this.entity.id = value;
}
}
public string name
{
get
{
return this.entity.name;
}
set
{
this.entity.name = value;
}
}
public int accountholder_id
{
get
{
return this.entity.accountholder_id;
}
set
{
this.entity.accountholder_id = value;
}
}
public System.Data.Linq.EntitySet<cAccountEntityValue> cAccountEntityValues
{
get
{
return this.entity.cAccountEntityValues;
}
}
public cAccountHolder cAccountHolder
{
get
{
return this.entity.cAccountHolder;
}
}
public cAccountEmployee()
{
this.entity = new cAccountEntity();
}
public cAccountEmployee(cAccountEntity entity)
{
this.entity = entity;
}
public string id_number
{
get
{
try
{
return this.entity.cAccountEntityValues.Single(e => e.type == 1).value;
}
catch (Exception)
{
return "";
}
}
set
{
try
{
this.entity.cAccountEntityValues.Single(e => e.type == 1).value = value;
}
catch (Exception)
{
this.entity.cAccountEntityValues.Add(new cAccountEntityValue()
{
accountentity_id = this.id,
cAccountEntity = this.entity,
type = 1,
value = value
});
}
}
}
}
//In the repository
public cAccountEmployee Single(int id)
{
return new cAccountEmployee(db.cAccountEntities.Single(a => a.id == id));
}
How can I get the base class Linq result to cast up to the inherited Employee class
It's not an upcast, it's a downcast.
I think you don't understand casting or possibly - instance type vs reference type.
public class Animal { }
public class Zebra : Animal { }
public class Zoo
{
public void ShowZebraCast()
{
Animal a = new Animal();
Zebra z = (Zebra)a;
}
}
System.InvalidCastException: Unable to cast object of type 'Animal' to type 'Zebra'.
In the same way, you have an instance of Entity that you can't downcast to use an Employee reference against it.
You could convert the types, but then you have to supply a conversion method.
public partial class Animal { }
public class Zebra : Animal { }
//in another file
public partial class Animal{
public Zebra ToZebra(){
return new Zebra() { //set Zebra properties here.
};
}
}
public class Zoo
{
public void ShowZebraConvert()
{
Animal a = new Animal();
Zebra z = a.ToZebra();
}
}

Categories