Force build to fail by some condition - c#

I have a class HierarchicalDictionary and some derived classes, for example Territory, Department, etc.
And I want to control that all classes that derive from HierarchicalDictionary contain property "Hierarchy" of type of that class (Territory, Department, etc.) during build. If it is not so I want build to fail.
That is if Territory doesn't contain property Hierarchy of type Territory or Department doesn't contain property Hierarchy of type Department, build should fail.
So I want that during compilation condition checked like that (pseudocode):
foreach (Class1 that derive from HierarchicalDictionary)
if(!(Class1 contains property Hierarchy of type Class1))
build fail
I thought about CodeContracts, but I don't know if there is availability to fail by condition during build.
May be there is some proper way?
UPD: I'll try to describe additional limitations for my situation:
HierarchicalDictionary is not stored (in database) class. And derived classes are stored, so corresponding tables contain self reference fields in database. When I derive class "C1" from HierarchicalDictionary I mean, that this class must contain property (or field) "Hierarchy" of type "C1" exactly. Like [ClassMustContainHierarchyFieldOfMyselfType] attribute. And I want to control that fact during compilation. If I have class "C2", that derives from HierarchicalDictionary and don't contain field (or property) "public C2 Hierarcy", build should fail.
May be there is no any "built-in" solutions. May be I can use pre- or post-build events or anything else (like CodeContracts for example)?

If HierarchicalDictionary can be abstract, you can define the property as abstract in the base class. This enforces a concrete implementation in every subclass.
If you need to be able to create instances of the base class HierarchicalDictionary you can enforce the property by adding an interface.

Well, may be you can do something like this:
// GENERIC base class
public abstract class A<T>
{
public abstract T GetMyType {get;}
}
//derived ones
public class B : A<B>
{
public override B GetMyType
{
get {
return new B();
}
}
}
public class C : A<C>
{
public override C GetMyType
{
get {
return new C();
}
}
}
and after in code:
new B().GetMyType.ToString(); //B
new C().GetMyType.ToString(); //C
So you create constrain with abstract method, plus every overriden method returns its own type, as they are derived from generic base class.

Related

C# inheritance vs. instantiation, what's the major difference and when to use what?

I've seen some old threads here, but I still can't find a concrete answer as to when to use either the best approach possible.
If you inherit, you get all the properties and methods.
If you instantiate, you get the same.
So is it the accessibility of those properties and methods that rely on either inheritance or instantiation?
Has it something to do with interfaces that a class is implementing, so that a decision is made to inherit that class, or instantiate?
Please enlighten. Thanks
EDIT:
#Gaz, question regarding your comment below:
class ParentClass {}
//why do this to create a child class to inherit the parent's properties and methods...
class ChildClassOne : ParentClass {}
//when you can do this?
var ChildClassOne = new ParentClass();
Thanks
Further to comments posted, your understanding of the example code is flawed.
class ParentClass {}
//why do this to create a child class to inherit the parent's properties and methods...
class ChildClassOne : ParentClass {}
//when you can do this?
var ChildClassOne = new ParentClass();
The return type of new ParentClass(); is an instance of ParentClass not ChildClassOne
Also as you have shown in this line that C# will allow you to name a variable after a class, which adds to the confusion, as you're creating a local scope variable of type ParentClass called ChildClassOne and assigning it an instance of ParentClass. Behind the scenes the var type is replaced by ParentClass
ParentClass ChildClassOne = new ParentClass(); might be clearer on that line, but just as confusing in later code.
Inheritance is for use when you may want one or more class types that exhibit common properties and methods e.g.
class ChildClassOne : ParentClass
{
int SomeInt{get;set;} //this doesn't exist in ParentClass
}
class ChildClassTwo : ParentClass
{
string SomeString{get;set;} //this doesn't exist in ParentClass
}
The above are definitions of a class.
Whenever a non-static class is instantiated a new block of memory is allocated for it and it can actually be used in code.
Now you can treat instances both ChildClassOne and ChildClassTwo as if they were a ParentClass e.g.
List<ParentClass> listOfClasses = new List<ParentClass>();
listOfClasses.Add(new ParentClass());
listOfClasses.Add(new ChildClassOne());
listOfClasses.Add(new ChildClassTwo());
So if ParentClass has a method DoSomething() that is not given private accessibility then you can do:
listOfClasses[0].DoSomething();
listOfClasses[1].DoSomething();
listOfClasses[2].DoSomething();
but if you wish to access child class properties or methods then you can run into issues.
var classValue = listOfClasses[0].SomeInt; will trigger an error at build time as ParentClass doesn't have such a property only ChildClassOne.
You may try to get passed the build error by casting
var classValue = ((ChildClassOne)listOfClasses[0]).SomeInt;
This will get you past the build stage but will trigger an exception at run time.
A real life analogy would be a parking lot.
The parking lot contains many vehicles. Some of the vehicles are SUVs, some are saloons, some are trucks).
Each one is an instance of both its type (saloon, truck, pickup, hatchback, SUV) but also its parent type - vehicle.
In this case all vehicles have wheels, but not all vehicles are the same, a truck is not an SUV.
If this is what you mean by instantiate,
A a = new A();
and this is what you mean by inheritance,
class B : A
{
...
}
Then my answer is inherit when writing a class that extends off of the base properties and behavior of the parent class, and instantiate when creating an object of the class for use at runtime.
Or have I misunderstood the question?
Inheritance is just a way of saying "this class contains all the properties and methods of the base class". It's no different from adding
public string Name { get; set; }
which says "this class contains a property called Name".
Inherited or not, all of these properties are available to the code within your class, because the code within your class only becomes viable once your class is instantiated at runtime.
All classes must be instantiated before they can be used (apart from static classes/methods). The code in your class is run in the context of one of those instantiations. Inheritance makes no difference.
The semantics convey all the differences. There can be several ways in which one class may use other.
Inheritance
One class derives from another
When you inherit one type from the other, you are saying that the derived type is a more specific base type. This would also mean that every derived type is also a base type. A derived type may represent a sub-category of the base type. However, it is also a common practice to use inheritance to add to the functionality of an existing class. However, ideally, inheritance is the right choice when the fundamental relationship between two entities is an is-a relationship. (Every Derived entity is also a Base entity as in every Employee is a Person)
class Person { }
class Employee : Person { }
Composition and Aggregation
When one class contains another
When you declare a entity as an entity in another class as an instance variable, it is called composition. Composition is, where an entity contains another entity to model membership. Specifically, composition is a has-a relationship. For instance, a Car may have several Wheels, a Post may have Comments.
It is worth noting that there are two variants of composition. An aggregation where the child has a separate existence outside its containing object like an Engine can still exist if the Car does not exist anymore. However, Room cannot exist if a Building ceases to exist. This is what is true composition. Mostly, an aggregation means a child can have multiple parents which is not the case with composition.
Association
One class uses another (as a parameter, return type or local variable)
Composition only applies when a variable is declared as an instance variable. If you have a local instance of one class in one of the methods of the other class or if it returns an object of one class or accepts it as parameter it does not involve composition. This is called an association, where a class depends on other classes to fulfill its responsibilities. As an example, a Passenger may need a Vehicle to travel:
class Passenger
{
public void Travel(Vehicle v) { }
}
Try to model your classes based on the nature of the relationship.
In the end, it is still a matter of opinion of when to use which.

WinForms Export UserControl derived class, but not in-between classes

I have a DLL that I'm making for Windows Forms applications. The layout looks a little something like this
public class A : UserControl
{
protected C c;
}
public class B : A { }
public class C { }
I want the DLL to only export class B, but it will not compile if I remove the public qualifier from A or C. Is there a way to do this?
Error from removing public from A:
Error CS0060 Inconsistent accessibility: base class 'A' is less accessible than class 'B'
From MSDN - Restrictions on Using Accessibility Levels (C# Reference):
When you specify a type in a declaration, check whether the accessibility level of the type is dependent on the accessibility level of a member or of another type. For example, the direct base class must be at least as accessible as the derived class.
Usually, in order to hide "stuff" from others, what you do, is provide a public interface and hide all the sub-classes. You can let your client create the concrete classes with a public factory which you will provide as well.
Not possible. If B inherits A, you simply cannot expose B without exposing A.

How can I store generic classes of different types (all with a generic base class) in the same collection?

I have a similar problem to the one in this post.
I have also seen the thousands of posts online that say that you can put any generic class that extends a particular base class into a collection of the type of the base class. I understand this perfectly well.
My problem differs from the linked post above and the others in one basic way - my generic classes have a base class that is also generic. Worse still, this is part of a very large MVVM application framework (built in-house) and the generic base class also has a base class and so on... each base class adds certain properties and functionality and it looks a bit like this:
DataListEntry<T> <-- BaseSynchronisableDataType<T> <--
BaseAuditDataType <-- BaseDataType <-- BaseAnimatableDataType
The application collection classes use similar inheritance:
DataList<T> <-- BaseSynchronisableCollection<T> <--
BaseAnimatableCollection<T> <-- BaseCollection<T> <--
SortableObservableCollection<T>
Even worse still, each generic declaration has constraints so that for instance, the definition of BaseSynchronisableDataType<T> looks like this:
public abstract class BaseSynchronisableDataType<T> : BaseAuditDataType,
ISynchronisable<T>, ICloneable<T>, IEquatable<T> where T : class, ICloneable<T>,
IEquatable<T>, new()
So each generic collection type is tied through these constraints to a generic base class. Hopefully by now, you can see the scale of my problem.
I have tried using interfaces (not shown above) to remove the link from the collections to their respective base classes, but this is also failing because of some of the generic constraints on related classes. For example, I couldn't create a collection of the type of an interface because there are neccessary generic 'class' constraints on some base classes and so I get errors saying that the type of the collection 'must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method'.
One last point to note describes exactly what I am trying to do:
I need to populate a collection with different classes that all extend the DataList<T> base class. These classes are different only in name and have exactly the same properties in them. They are declared as follows:
public class Writer : DataListEntry<Writer>
public class Artist : DataListEntry<Artist>etc.
If you have any ideas, then please let me know... I've suffered for 2 days on this problem already and my boss is none too pleased! Many thanks in advance, Sheridan.
There's a key principle in play here that you need to understand- that a class Foo<Child> is not a subclass of Foo<Parent> even when Child is a subclass of Parent. That means that a List<Foo<Parent>> cannot contain instances of List<Foo<Child>> any more than it can contain Strings or Int32s.
To understand why this is the case, imagine the following code (which doesnt compile, but illustrates why the above statement needs to be true):
var myIntList = new List<Int>();
var myObjectList = (List<Object>)myIntList;
// Uh oh, now I can add a string to a list of integers...
myObjectList.Add("Foo");
Your use of the curiously recurring template pattern eliminates the inheritance hierarchy between all of your classes. Because they don't share a base class anymore, they cannot be put into a list more specific than List<Object>
The best approach in your case is probably to make a non-generic interface which DataListEntry implements, and make your list of that interface. If the interface provides all of the members that you need in an instance of that type, you are all set.
For example:
public interface IDataListEntry {
bool QuacksLikeADuck { get; }
bool WalksLikeADuck { get; }
}
public abstract class DataListEntry<T> : IDataListEntry where ... {
// Implement these in subclasses
abstract bool QuacksLikeADuck { get; }
abstract bool WalksLikeADuck { get; }
}
Then you can:
List<IDataListEntry> myDataListEntries = new List<IDataListEntry>();
myDataListEntries.Add(new Writer(...));
myDataListEntries.Add(new Artist(...));
IEnumerable ducks = myDataListEntries.Where(dle => dle.WalksLikeADuck && dle.QuacksLikeADuck);
Or (probably more appropriate to your situation), if you need to know the Type of the T in the particular instance of the IDataListEntry:
public interface IDataListEntry {
Type TheTypeOfT { get; }
}
public class DataListEntry<T> : IDataListEntry where ... {
Type TheTypeOfT { get { return typeof(T); } }
}
and then do:
List<IDataListEntry> myDataListEntries = new List<IDataListEntry>();
myDataListEntries.Add(new Writer(...));
myDataListEntries.Add(new Artist(...));
IEnumerable artists = myDataListEntries.Where(dle => typeof(Artist).IsAssignableFrom(dle.TheTypeOfT));
I would go all the way back to the basics, and use some simple linq to get the class filtered list.
Declare you list of type object DataList<object> L then when you get asked for a type, call L.OfType<Type>() which filters the list. object is going to be the most generic thing you can use after all. you Might be able to use the base type that the all extend, but because its abstract I dont know if you can declare a list on that type or not.
in my own code, I use generic constraints to achieve something similar.
public abstract class BusinessObjectBase : //some interfaces
{
//class stuff and events
}
I have a bunch of objects delcared that extend my base class, and now I can do this
Collection<BusinessObjectBase> temp = new Collection<BusinessObjectBase>();
temp.Add(new RXEvents());
temp.Add(new RXBattery());
temp.Add(new RXBHA());
where each of those classes Im adding to the list are all creating by extending BusinessObjectBase. You are attempting something very similar, but your base implementation is different. By declaring the base type itself as templated, you are breaking the base type. Base is note the same as Base, and the two dont implement anything in common other than object.
Base<> is not related to Base<X> or Base<Y>. Now if you delcared it like this
public abstract class BaseSynchronisableDataType<T> : BaseAuditDataType, ISynchronisable<T>, ICloneable<T>, IEquatable<T> where T : MyCustomBaseClass, ICloneable<T>, IEquatable<T>, new()
You could then use MyCustomBaseClass as the list type, because you are guaranteed that all the objects that <T> represents, are its children. This would seem to defeat the purpose of creating the BaseSynchronisableDataType though...
Ok, so the problem was that I couldn't declare the following
DataList<Artist> artists = new DataList<Artist>();
when the BaseDataListEntry class was NOT generic because of a generic constraint on the generic BaseSynchronisableCollection<T> class that DataList<T> extends. It required T to be of the type BaseSynchronisableDataType<T> which the BaseDataListEntry class could not extend because it was not generic. I needed the BaseDataListEntry class to NOT be generic so that I could put all the different collections of DataList<T> into a collection of DataList<BaseDataListEntry> in the view model (one at a time dependant on the user's selection).
The solution was to create an IBaseSynchronisableDataType<T> interface and use that in the generic constraint instead of the concrete BaseSynchronisableDataType<T> class. Then, I implemented that in the BaseDataListEntry class, so now all the constraints are satisfied. Not sure why I didn't see it earlier.
Thanks for all you time.

c# Factory Method and protection levels problem

I have a base class and several subclasses derived from that base class. I also have a static function in the base class that takes some parameters, and instantiates and returns an appropriate subclass based on input parameters ( my factory method.)
Now here's my problem: I want to ONLY allow instantiation of the subclasses FROM the factory method. But if I set the constructors of the subclasses to be protected, the base class can't see them. Is there an access modifier I'm missing that would allow the base class to call the subclasses constructors, but not not allow any other classes to call them?
Internal doesn't look like it will work either...I want to limit access to the subclass constructors to just the base class, there are other classes in the same assembly that should be able to access the base factory method and but not directly instantiate any of the subclasses.
Hopefully there's something really simple I'm missing...
Example:
public class Base
{
public Base CreateChild(string childType)
{
if(childType == "A")
return new ChildA();
if(childType == "B")
return new ChildB();
return null;
}
}
public class ChildA
{
protected ChildA() // This doesn't work, since now base class can't call this!
{
}
}
public class ChildB
{
protected ChildB()
{
}
}
You can declare the child classes as private nested classes inside Base
Have you tried declaring the child classes within the base class?
public class Base {
protected class ChildA {}
protected class ChildB {}
}
If accessing any derived object through the base type is a valid scenario (let's say derived types only override base implementations and do not add new functionality) then the proposed solution of making the derived types nested private classes (as previous answers propose) is the best solution.
If that's not the case then I think you are falling into a case of unjustified complexity. What is the reason why code from your same assembly can not access ChildA and ChildB constructors? It is after all code you can control, so you can always choose to make / enforce via code review that he initalization is through the factory method.
I understand there is valid reasons to not let external assemblies freely instantiate objects except through a tightly controlled mechanism. In this case just marking the constructors as internal would do.
Otherwise, I'm not sure you can achieve what you are pretending without creating a specific assembly just for this base class and its derived classes. There is definitely no access modifier that would make a static method in a derived class only visible from it's base class.

How to prevent inheritance for some methods?

How can I prevent inheritance of some methods or properties in derived classes?!
public class BaseClass : Collection
{
//Some operations...
//Should not let derived classes inherit 'Add' method.
}
public class DerivedClass : BaseClass
{
public void DoSomething(int Item)
{
this.Add(Item); // Error: No such method should exist...
}
}
The pattern you want is composition ("Has-a"), not inheritance ("Is-a"). BaseClass should contain a collection, not inherit from collection. BaseClass can then selectively choose what methods or properties to expose on its interface. Most of those may just be passthroughs that call the equivalent methods on the internal collection.
Marking things private in the child classes won't work, because anyone with a base type variable (Collection x = new DerivedClass()) will still be able to access the "hidden" members through the base type.
If "Is-a" vs "Has-a" doesn't click for you, think of it in terms of parents vs friends. You can't choose your parents and can't remove them from your DNA, but you can choose who you associate with.
You can't, in this instance inheritance is the wrong tool for the job. Your class needs to have the collection as a private member, then you can expose as much or as little of it as you wish.
Trying to hide a public member of a class in a derived class is generally a bad thing(*). Trying to hide it as a means of ensuring it won't be called is even worse, and generally won't work anyhow.
There isn't any standardized idiomatic means I know of to prevent a parent class' protected member from being accessed in a sub-derived type, but declaring a new public useless member of a clearly-useless kind would be one approach. The simplest such thing would be an empty class. For example, if class Foo declares an empty public class called MemberwiseClone, derivatives of Foo will be unable to call MemberwiseClone--probably a good thing if MemberwiseClone would break the invariants of class Foo.
(*) The only situation where it is appropriate is when a public method of a derived class returns a more specialized type than the corresponding method in the base class (e.g. a CarFactory.Produce() method may return a Car, while the FordExplorerFactory.Produce() method may return a FordExplorer (which derives from car). Someone who calls Produce() on what they think is a CarFactory (but happens to be a FordExplorerFactory) will get a Car (which happens to be a FordExplorer), but someone who calls Produce() on what is known at compile time to be a FordExplorerFactory will get a result that's known at compile time to be a FordExplorer.

Categories

Resources