I'm trying to access a field from a derived class in an array that holds references to the base class.
I have three classes:
abstract GameObjectBase
{
}
And derived from that are:
public Gamespace: GameObjectBase
{
private bool containsItem;
}
And:
public GameWall: GameObjectBase
{
}
(Obviously these classes hold more data, methods, and constructors).
I have created an array from these objects, like this
private GameObjectBase[,] _labyrinthArray = new GameObjectBase[10,10];
I then fill said array with Gamespaces and Gamewalls. But when I access a Gamespace object in the array, the containsItem field is not accessible due to the reference to the object being of type GameObjectBase.
Obviously I could put containsItem in GameObjectBase and make it accessible from there, but that doesn't fit my OOP approach. The only other solution I have found is to cast the object in question explicitely to Gamespace.
That seems quite crude and error prone to me. Is there any better solution to this?
First of all, you cannot reference a private field from outside the object class itself. You probably want to use a read-only property to encapsulate the field. If you don't want to cast the object explicitly to a Gamespace, you could use an interface instead.
public interface ICanContainItem
{
bool ContainsItem { get; }
}
public class Gamespace : GameObjectBase, ICanContainItem
{
private bool _containsItem;
public bool ContainsItem
{
get { return _containsItem; }
private set { _containsItem = value; }
}
}
This way you can then check whether the object "can contain an item" or not through the interface. Even if in the future you add new types of spaces that can contain an item, this same piece of code works, if the new types also implement the same interface.
var gameObject = _labyrinthArray[i,j]; //i,j defined elsewhere
var mayContainItem = gameObject as ICanContainItem;
if (mayContainItem != null)
{
var itemExists = mayContainItem.ContainsItem;
//mayContainItem.ContainsItem = false; //<-- fails because there's no setter
}
Related
I have a class that has a field that is being assigned a value from multiple methods.
public class Shape
{
private Point2D m_location;
public void Move()
{
m_location = ...
}
public void Rotate()
{
m_location = ...
}
public void Flip()
{
m_location = ...
}
}
I am getting a warning from NDepend that says:
Don't assign a field from many methods
https://www.ndepend.com/default-rules/Q_Don't_assign_a_field_from_many_methods.html
I am thinking of solving this problem by creating a separate method to assign the value of the field and calling this method from the other methods that currently assign a value to the field.
Here is an example of the code:
private void SetLocation(Point2D point)
{
m_location = location;
}
I want to know if this is a valid way to solve the problem and if it will just hide the code-smell that NDepend detected or actually fix the issue.
Is this a valid way to solve this problem?
No. As you suspect, this is a code smell. What NDepend is complaining about is mutable references; you have code where:
var s = new SomeObject(someInitialization);
var r = s.SomeResult();
// you now have no idea what s contains or if it is even usable any more.
The solution to this is to make SomeObject immutable and return new references instead of changing internals:
public SomeObject Something()
{
return new SomeObject(SomethingDifferentDependingOn(this.something));
}
Now instead of your first example you have:
var s = new SomeObject(someInitialization);
var r = s.Something().Result;
// s is guaranteed to be unchanged.
Yes some times you will need mutable references. In those cases; document them and explain why they have to be mutable. Then you can override NDepend rules on a case-by-case basis to prevent it showing a warning. If you have a code smell, warn people. Do not try to hide it.
The example after your edit is quite different, but the general principle still holds. If you have only a few internal fields that all change in method calls you can still return immutable references, e.g.:
public Shape Move()
{
return new Shape(m_location ...);
}
If you have many internal fields that don't all change, or you need to do something like share private fields you can't easily have immutable reference, but you can still avoid the warning by using accessors:
public Location
{
get { return m_location; }
private set { m_location = value; }
}
Then use Shape.Location exclusively in your internal methods.
I have data from multiple organisations (police, fire, office) that need output in different formats.
To achieve this, I defined the following (this is a little simplified):
Transaction class -
"Success" indicator - Boolean.
"Type of department"- String or Enum.
A class which can be of any type - Police, Fire or Office (My question is on this as you will see).
A GenerateOutput() method - to handle generation of file formats.
Police class
Age - String
VehicleNumber - Integer
Supervisor - String
Fire class
Name - String
FireEngineNumber - Integer
County - Enum
WorkTimings - Enum
Office Class
Age - String
DeskNumber - Integer
Department - String
PayScale - Enum
IsManagement - Bool
As you can see, the Police, Fire and Office classes dont share anything in common and are primarily intended as data carrying entities. I intend to use a Factory to return an appropriate generic (not a C# generic) Transaction object with the data (Transaction object with Police, Fire or Office data within it) and then pass the returned object to a Strategy pattern which determines the file format (CSV, Excel, or XML; specified in a configuration file) each one needs.
My problem is in the definition of the Transaction object.
What type does the class in "3." of the Transaction class need to be? The data for each org differs, there are no common members, I am unable to define a common class for all.
Is the overall design appropriate? What other designs should I consider?
Based on Peter's comments below:
I think using generics might work, I ran into a problem though. I would like to use a factory to return the object requested, using GetTransactionObject, as below. What should be the return type of GetTransactionObject to accomodate this.
class TransactionFactory
{
Dictionary<string, Type> typeClassLookup;
public TransactionFactory()
{
typeClassLookup = new Dictionary<string, Type>();
typeClassLookup.Add("Police", typeof(PoliceData));
typeClassLookup.Add("Fire", typeof(FireData));
}
Transaction<????> GetTransactionObject(string org)
{
if( typeClassLookup.TryGetValue(org, out typeValue))
{
switch (typeValue.ToString())
{
case "policeData":
transactionObject = new Transaction<PoliceData>() { Data = new PoliceData(), params = null};
case "FireData":
transactionObject = new Transaction<FireData>() {Data = new FireData(), params = null};
}
}
return transactionObject;
If the types really have nothing in common, then you need no explicit base class. System.Object suffices, just as with many other generic types (i.e. any generic type lacking a constraint).
In other words, you could declare as:
class Transaction<T>
{
public bool Success { get; private set; }
public T Entity { get; private set; }
public Transaction(bool success, T entity)
{
Success = success;
Entity = entity;
}
public void GenerateOutput() { /* something goes here */ }
}
Personally, I would avoid adding a "department type" member. After all, that's implicit from the type parameter T. But you could add that easily to the above if you want.
If and when you find that the types do have something in common, such that your Transaction<T> type needs to do more than simply hold onto an instance of one of those types (which is about all it can do without a constraint), then you will be able to put that commonality into an interface or base class (depending on the specific need), and specify that in a constraint for the Transaction<T> class.
Note that it's not clear what you mean for the GenerateOutput() to do, or how it should work. But assuming that you want output that is specific for each Entity value, it seems to me that that is your "something in common". I.e., it's not the Transaction<T> class at all that needs to implement that method, but rather each entity type. In that case, you have something like this:
interface IDepartmentEntity
{
void GenerateOutput();
}
class Office : IDepartmentEntity
{
public void GenerateOutput() { /* department-specific logic here */ }
}
// etc.
Then you can declare:
class Transaction<T> where T : IDepartmentEntity
{
public bool Success { get; private set; }
public T Entity { get; private set; }
public Transaction(bool success, T entity)
{
Success = success;
Entity = entity;
}
public void GenerateOutput() { Entity.GenerateOutput(); }
}
EDIT:
Per Prasant's follow-up edit, with a request for advice on the GetTransactionObject()…
The right way to do this depends on the caller and the context, a detail not provided in the question. IMHO, the best scenario is where the caller is aware of the type. This allows the full power of generics to be used.
For example:
class TransactionFactory
{
public Transaction<T> GetTransactionObject<T>()
where T : IDepartmentEntity, new()
{
return new Transaction<T>()
{
Data = new T(),
params = null
}
}
}
Then you call like this:
Transaction<FireData> transaction = factory.GetTransactionObject<FireData>();
The caller, of course already knowing the type it is creating, then can fill in the appropriate properties of the transaction.Data object.
If that approach is not possible, then you will need for Transaction<T> itself to have a base class, or implement an interface. Note that in my original example, the IDepartmentEntity interface has only one method, and it's the same as the GenerateOutput() method in the Transaction class.
So maybe, that interface is really about generating output instead of being a data entity. Call it, instead of IDepartmentEntity, something like IOutputGenerator.
In that case, you might have something like this:
class Transaction<T> : IOutputGenerator
{
// all as before
}
class TransactionFactory
{
public IOutputGenerator GetTransactionObject(string org)
{
if( typeClassLookup.TryGetValue(org, out typeValue))
{
switch (typeValue.ToString())
{
case "policeData":
transactionObject = new Transaction<PoliceData>() { Data = new PoliceData(), params = null};
case "FireData":
transactionObject = new Transaction<FireData>() {Data = new FireData(), params = null};
}
}
return transactionObject;
}
}
This is an inferior solution, as it means the caller can only directly access the IOutputGenerator functionality. Anything else requires doing some type-checking and special-case code, something that really ought to be avoided whenever possible.
Note: if the Transaction type has other members which, like the GenerateOutput() method, are independent of the contained type T here, and which would be useful to callers who don't know T, then a possible variation of the above is to not reuse the interface used for the department-specific data types, but instead declare a base class for Transaction<T>, named of course Transaction, containing all those members not related to T. Then the return value can be Transaction.
What type does the class in "3." of the Transaction class need to be?
To decouple your department classes from the various export types, I recommend you make the department classes implement a common interface. Something like this:
public interface Exportable {
// return a list of attribute names, values, and types to export
IList<Tuple<String, String, Type>> GetAttributes();
}
For example:
public class Police : Exportable {
public IList<Tuple<String, String, Type>> GetAttributes() {
// return list size 3 - attribute info for Age, VehicleNumber, Supervisor
}
}
Is the overall design appropriate? What other designs should I consider?
The Transaction class design doesn't seem well suited for this problem.
Consider an Export class with a method for each export type, each method which receives the attributes returned from the Exportable interface method. Basic outline:
public static class Export {
public static boolean CSV(IList<Tuple<String, String, Type>> attributes) {
// export attributes to CSV, return whether succeeded
}
public static boolean Excel(IList<Tuple<String, String, Type>> attributes) {
// export attributes to Excel, return whether succeeded
}
// same thing for XML
}
I have 2 variables
Date-Time-Modified which is a Date-Time variables
Is-Deleted variable which is a boolean.
These two variables are found in each class I have and I need to have these variables initialized each time I insert, edit or delete an object from my database. Is there a way to do this?
Use a base class. Add the 2 needed properties (DateTime, IsDeleted). Every derived class now holds this properties. You can set them individually or iterate over the base type to assign a value.
You can also use events to trigger the update automatically. But i think you just want to create an entry and then set its DateTime property to the actual date time.
You also could delegate this task to the database. It will take care of setting this attributes.
An example for my lazy friend ;)
abstract class DatabaseEntryBase
{
public DatabaseEntryBase()
{
// You can initialize properties to a default value here
this.IsDeleted = false;
}
public DateTime ModifiedTime { get; set; }
public bool IsDeleted { get; set; }
}
class Entry : DatabaseEntryBase
{}
static void Main()
{
//-- Do your SQL stuff --//
var newEntry = new Entry();
newEntry.ModifiedTime = DateTime.Now;
newEntry.IsDeleted = false;
}
If you need all instances to hold the same values (e.g. multiple deletes) push them into a collection (here EntryCollection of type List<DatabaseEntryBase>) and iterate over them instead:
public void SetAllItems()
{
foreach (DatabaseEntryBase entry in EntryCollection)
{
entry.ModifiedTime = DateTime.Now;
entry.IsDeleted = [...];
}
}
Using an interface will accomplish the same! It could be named ITaggable and defines this two properties as a contract.
Have a base class that has these members and then have the other classes extend that one.
Then have a method on the base that initalises them. Then call that method on the inserts and such.
base.InitialiseVariables()
Is there any other way to just initialize them without the need of
calling a method?
Probably another approach for this is Aspect-Oriented Programming. For example, PostSharp.
Code will look something like this:
[UpdateTimestamp]
public void InsertProduct(Product product)
{
// Your logic here
}
Consider the class:
public class foo
{
public object newObject
{
get
{
return new object();
}
}
}
According to MSDN:
Properties are members that provide a flexible mechanism to read,
write, or compute the values of private fields. Properties can be used
as though they are public data members, but they are actually special
methods called accessors. This enables data to be accessed easily
And:
Properties enable a class to expose a public way of getting and
setting values, while hiding implementation or verification code.
A get property accessor is used to return the property value, and a
set accessor is used to assign a new value. These accessors can have
different access levels. For more information, see Accessor
Accessibility.
The value keyword is used to define the value being assigned by the
set indexer.
Properties that do not implement a set method are read only.
while still providing the safety and flexibility of methods.
Does this therefore mean that at some point in time the value of the newObject property has a reference to the returned new object?
edit removed readonly from property
edit2 also would like to clarify that this is not the best use for a property but its done to try and illustrate the question more effectively.
You return a new object on each access to the property and that is not the expected behavior of properties. Instead you should return the same value each time (e.g. a value stored in a field). A property getter is simply glorified syntax for a method that returns a value. Your code compiles into something like this (the compiler creates a getter by prefixing the property name with get_ which is then emitted as IL):
public class foo
{
public object get_newObject()
{
return new object();
}
}
Each call to the getter will create a new object that foo doesn't know about or has access to.
Does this therefore mean that at some point in time the value of the newObject property has a reference to the returned new object?
No.
Property using a backing field:
class Foo {
readonly Object bar = new Object();
public Object Bar { get { return this.bar; } }
}
Using automatic properties:
class Foo {
public Foo() {
Bar = new Object();
}
public Object Bar { get; private set; }
}
A property is accessed using the same easy syntax as a public field. However, by using a property you can add code to the getter and the setter allowing you to do stuff like lazy loading in the getter or validation in the setter (and much more).
Under the hood, your property will simply be calling a function named get_newObject() that looks like this:
public object get_newObject()
{
return new object();
}
Since that is the case, it will always return a new object every time it is invoked.
If you want to retain a reference to the object, then I would recommend creating a private field to hold the data and having the property access that field, like so:
private object myObject;
public object newObject
{
if(myObject == null)
{
myObject = new object();
}
return myObject;
}
Since your property doesn't define set, and your field is private, newObject is basically eradonly outside of the containing class.
Properties in C# are "syntactic sugar". The code within the get block of a property is in fact put into a hidden get_PropertyName() method, and the set block into a hidden set_PropertyName() method. In the case of your code, the following method will be created:
public object get_newObject()
{
return new object();
}
You can see these hidden methods if you view the compiled assembly using Reflector, or ildasm.
When the property is used, the C# compiler converts any "get" accesses of your property into calls of the get_newObject() method. As an example:
If you were to write the following:
var foo = new foo();
var aNewObject = foo.newObject;
The compiler would convert that to:
var foo = new foo();
var aNewObject = foo.get_newObject();
So, in answer to your other question, the newly created object returned when someone "gets" the property won't be stored within your foo instance, the caller will simply get a new object every time.
Not exactly. Properties are just syntactic sugar so that you don't have to write accessor methods (like Java).
So this:
private int _myInteger;
public int MyInteger
{
get { return _myInteger; }
set { _myInteger = value; }
}
is equivilant to this:
private int _myInteger;
public int GetMyInteger()
{
return _myInteger;
}
public void SetMyInteger(int value)
{
_myInteger = value;
}
and it gets better with this, which is also equivilant:
public int MyInteger { get; set; }
I'm creating a list of class "Task" in a way such as this.
List<Task> toDoList = new List<Task>;
Task is a base class and have designed it as such:
public class Task : IDetail
{
string _taskName; //Task title.
string _taskDescription; //Task description.
public Task(string tn, string td) //Constructor.
{
_taskName = tn;
_taskDescription = td;
}
// Method set or return _taskName.
public string taskName
{
get
{
return _taskName;
}
set
{
_taskName = value;
}
}
//Method to set or return _taskDescription.
public string taskDescription
{
get
{
return _taskDescription;
}
set
{
_taskDescription = value;
}
}
public virtual void editList()
{
Creator editCreator = new Creator();
editCreator.Show();
}
}
What i've been trying todo is call methods that exists within the inherited class like one the one i have designate "Note" and have defined it as follows.
class Note : Task, IDetail
{
string _noteDescription;
public Note(string nd, string tn, string td) //Constructor.
: base(tn, td)
{
_noteDescription = nd;
}
//Method to set or return _noteDescription.
public string noteDescription
{
get
{
return _noteDescription;
}
set
{
_noteDescription = value;
}
}
public override void editList()
{
noteBuilder editNote = new noteBuilder();
editNote.Show();
}
}
However when i try to call a method of the inherited task on the list i get an error. I am trying to access the method as such:
toDoList.ElementAt(x).noteDescription;
My question is how do i prevent an error from occurring?
the error states
'toDoList.Task' does not contain a definition for 'noteDescription' and no extension method etc etc.
Should i perhaps be declaring the base class as Abstract? or is there something else i am missing?
Many thanks in advance
You've got a List<Task>. That could contain any kind of Task reference - e.g. a different derived type, not a Note. Either you want a List<Note> (so it can all be type-safe), or you'll need to cast the element of the list to Note:
Note note = (Note) toDoList[x];
string description = note.noteDescription;
(Given that you've got a List<T>, you don't need to use ElementAt - use the indexer.)
Filter the list and convert them to notes, like:
var noteList = toDoList.Where(x => x is Note)
.Select(x => (Note)x)
.ToList();
then write
noteList.ElementAt(x).noteDescription;
Because Your list is a list of Task objects, not Note objects.
You'll need to cast your objects to Note objects before you can call methods of the Note class.
(toDoList.ElementAt(x) as Note).noteDescription;
or
toDoList.Cast<Note>().ElementAt(x).noteDescription;
The second option requires all objects in the list be Note objects.
notDescription is a property you have for your derived class. But here you are creating a list of your base class
List<Task> toDoList = new List<Task>;
You can not get the properties of derived class in a base class. IT works the other way. You can access the properties of base class in your child class.
toDoList contains Task elements, not Note elements. Now a Note element is a type of Task element, sure, but polymorphism only works in one direction: you can treat a subclass like its superclass, but you can't treat a superclass like a subclass without casting it first.
If you think about it, you'll realize that it has to be that way. What if you had a second subclass of Task called Foo: you can put both of those types in toDoList...if you tried to access noteDescription on an object that is of type Foo, you'd be in trouble.
However, there is a way to do what you want, it just requires a cast:
var note = toDoList.ElementAt(x) as Note;
var noteDescription = note==null ? "<not a note>" : note.noteDescription;
The other way to do it, of course, would be to move noteDescription into Todo, where it would be accessible from any subclass of Todo, but that's probably not what you want since the name implies that it belongs to Note.