How declare a generic class field inside abstract class - c#

I would like to declare a generic field inside PakFileFormat class in order to be replaceable with concrete types in derived classes.
This will be fine:
public class Pak10File : PakFileFormat
{
public Pak10File()
{
this.toc = new PakFileToc<Pak10FileEntry>();
}
}
How to fix this ?
Thanks.
Related classes
public abstract class PakFileEntry { }
public class Pak10FileEntry : PakFileEntry
{
public long size; // 8 bytes
public long csize; // 8 bytes
public long offset; // 8 bytes
public byte fname_len; // 1 byte
public char[] fname; // variable
}
public class PakFileToc<T> where T : PakFileEntry { }
public abstract class PakFileFormat
{
protected PakFileToc<T>; // ----- This does not compile.
}

You would need to make PakFileFormat generic also in order to make that compile.
In order for this to be useful though, you will probably need to make PakFileFormat implement some kind of non-generic interface.
It is hard to give more detail than this without knowing exactly what you need PakFileFormat to actually do, or how it will be used.
public abstract class PakFileFormat<TPakFile> where TPakFile : PakFileEntry
{
protected PakFileToc<TPakFile> toc;
}
The sub-classes would then look something like:
public class Pak10File : PakFileFormat<Pak10FileEntry>
{
public Pak10File()
{
this.toc = new PakFileToc<Pak10FileEntry>();
}
}

Related

Can I inherit from a class if base class doesn't have constructor

So I have a Vehicle class without a constructor. I want to make a new class called VehicleExtended which inherits from Vehicle.
The error is:
'Vehicle' does not contain a constructor that takes 0 arguments (CS1729)
Is it possible to inherit without having a constructor?
NOTE: I can't edit the base class because it's only it's metadata that I can see.
public class VehicleData : Vehicle
{
[BsonId]public int _id { get; private set;}
public bool IsCompany { get; private set;}
public int OwnerID { get; private set; }
public string modelName { get; private set;}
}
As we can see from the error message, base class Vehicle doesn't have constructors without arguments:
public class Vehicle {
...
// every Vehicle constructors want some parameters, e.g. id and ownerId
public Vehicle(int id, int ownerId) {...}
...
}
That's the compiler doesn't know how to create instance of VehicleData:
// Since VehicleData is inherited from Vehicle,
// Vehicle cosntructor should be executed.
// What arguments should be passed to it?
var test = new VehicleData();
You have to implement VehicleData constructor manually in which you should specify the arguments:
public class VehicleData : Vehicle
{
// When creating an instace, use -1 and -1 when calling base constructor
public VehicleData() : base(-1, -1) {}
...
}
Now the code above is legal:
// We don't want parameters when creating VehicleData instance
// When creating base class (Vehicle) -1 and -1 are used
var test = new VehicleData();
Edit: If base class (Vehicle) doesn't have any public or protected constructors (but private ones) you can't create base Vehicle instance from VehicleData and thus can't inherit from Vehicle. private constructors only is an old C++ trick; in case of C# in order to prevent from inheriting we should use sealed
It's possible, that the base class has a private constructor which can't be accessed. In this case you can't inherit the class.
Based on the error message I assume that the class VehicleData has an private zero argument constructor.
In this case you can not inherit from VehicleData.
e.g.
public class A
{
private A() {}
}
public class B : A
{
}
this will not compile.
But if there is an public or protected with a non-zeor argument list you can inherit from the class:
public class A
{
private A() {}
public A(int i) {}
}
public class B : A
{
public B() : base(0) {}
}
Also, if it turns out that Vehicle has only private constructores and you only want to add specificy behaivor and not any kinds of properties that are not computable from the ones that are already defined in Vehicle, instead of inheriting you could use extesnions-methodes.
public static VehicleExtesnion
{
public SomeType DoStuff(this Vehicle vehicle)
{
// do stuff with vehicle
}
}

Declaring Method with generic type

I was using generic types in C# and I am new to using generic types. So, right now I am stuck with a problem. I have some classes like these:
public class MyModel1
{
}
public class MyModel2
{
}
public class BaseClass<T>
{
}
public class ChildClass1 : BaseClass<MyModel1>
{
}
public class ChildClass2 : BaseClass<MyModel2>
{
}
public class AnotherClass
{
//What will be the syntax of declaring this method
//The syntax of the following method is wrong and incomplete.
//It's there just to give an idea about whai i want to do.
public void MyMethod<T>()
where T : BaseClass<..what to write..>
{
}
}
My question is what will be the correct syntax of declaring MyMethod if I want to call MyMethod like this:
MyMethod<ChildClass1>();
If I understood correctly, you try to filter "MyMethod" so that T is a class of type "ChildClass ...".
You can add a generic parameter to your function like this:
public void MyMethod<T, U>()
where T : BaseClass<U>
{
}
But then you have to call MyMethod in that way.
MyMethod<ChildClass1, MyModel1>();
So it's quite complicated to use.
Another solution is to create a new "blank" class :
public abstract class Base // mark it as abstract if you don't need to use it in your code
{
}
public class MyModel1
{
}
public class MyModel2
{
}
public class BaseClass<T> : Base //The class inherits the new class
{
}
public class ChildClass1 : BaseClass<MyModel1>
{
}
public class ChildClass2 : BaseClass<MyModel2>
{
}
public class AnotherClass
{
public void MyMethod<T>()
where T : Base
{
}
}
You've forgotten to mention the return type and adding <T> after the class name. For example, if the return type is void, you could declare the method as:
public void MyMethod<T>()
where T : BaseClass<T>
{
}
This will work (by which I mean it compiles)
public void MyMethod<T>()
where T : BaseClass<MyModel1>
{ }
so does this:
public void MyMethod<T>()
where T : ChildClass1
{ }
Further edit after reading your comment...
You can do this:
public class AnotherClass<TBaseClass, TModel> where TBaseClass : BaseClass<TModel>
{
public void MyMethod(TBaseClass input)
{ }
}
I have a term for this, hopefully non-offensive. I call it The Generic Rabbit Hole of Madness. It's what happens when we try to combine generics and inheritance so that one set of classes can accomplish a broad set of goals that become increasingly confusing, and we solve it by adding more generic parameters and more generic classes.
You reach the bottom of the hole if you
- use <dynamic>
- check to see what the actual type is using GetType(), typeof, or is
- get it to compile but can't remember what it's supposed to do

Understanding polymorphism in general (c# example)

I am currently in the middle of self-teaching some basic concepts of C# and I am experimenting with abstract classes and polymorphism. I thought I got the basic concept but it turned out that the concept doesn't work like I understood it :). However - I hope I get some answers which clear the dust a little bit :).
The whole task I am trying to achieve is to extend an abstract base class and use the extension with an object of the base class. Like here:
I have an abstract class which implements an abstract property like:
public abstract class BaseClass
{
public abstract MyProperty mP{get;}
}
where the property is
public abstract class MyProperty
{
public abstract string PropertyName{get;}
}
Now I am deriving the MyProperty class for an actual implementation like
public class DerivedProperty : MyProperty
{
public override string PropertyName
{
get
{
return this._name;
}
}
private _name = "Property1";
/* some other implementation follows here...... */
}
As I've understood polymorphism and inheritance it should now be possible to instantiate a derived class from BaseClass and override the property MyProperty with an object of DerivedProperty like this:
public class DerivedClass : BaseClass
{
public override DerivedProperty mP
{
get
{
return dP;
}
}
private DerivedProperty dP = new DerivedProperty();
/* more implementation follows here...... */
}
Because DerivedProperty is an object of MyProperty and DerivedProperty at the same time it is possible to use it where either MyProperty or DerivedProperty is referenced. At least that's what I thought but it seems that this is wrong.
Now I am wondering - why is polymorphism so useful when something like above is not possible? Because even when I try something like this:
public class DerivedClass : BaseClass
{
public override MyProperty mP
{
get
{
return dP as DerivedProperty;
}
}
private DerivedProperty dP = new DerivedProperty();
/* more implementation follows here...... */
}
I still get only my base object MyProperty and not my extended object DerivedProperty which I want to get.
I know why I get those results - I just don't seem logical to me :). Is it really like polymorphism is supposed to work or is my implementation just crap and I have to do it in a different way to get my extended property?
Appreciate your help here!
You have to provide the same type for overrided property. You can use it later in your abstract BaseClass. Parameters as well as return value of member have to be the same when overriding. It is usually not a problem.
I've prepared following examples that my code look similar to yours.
In some scenarios I've seen that there is added second property with more specific type and different (more specific) name:
public abstract class BaseCar
{
public abstract BaseDriver Driver { get; }
}
public abstract class BaseDriver
{
public abstract string Name { get; set; }
}
public class AgressiveDriver : BaseDriver
{
public override string Name { get; set; }
}
public class FastCar : BaseCar
{
private AgressiveDriver _agressiveDriver = new AgressiveDriver();
public override BaseDriver Driver { get { return _agressiveDriver; } }
public AgressiveDriver AgressiveDriver { get { return _agressiveDriver; } }
}
Second approach is to use generics:
public abstract class BaseCar<TDriver>
where TDriver : BaseDriver
{
public abstract TDriver Driver { get; }
}
public abstract class BaseDriver
{
public abstract string Name { get; set; }
}
public class AgressiveDriver : BaseDriver
{
public override string Name { get; set; }
}
public class FastCar : BaseCar<AgressiveDriver>
{
private AgressiveDriver _agressiveDriver = new AgressiveDriver();
public override AgressiveDriver Driver { get { return _agressiveDriver; } }
}
but I think first approach is better because there is no problem with creating/using BaseCar objects (for example to create BaseCar<> variable you have to specify type parameter). Also it makes sense to create more specific name for more specific property.
I think you have an extra bit of complexity you don't need. You have an abstract class inside an abstract class. If you are just learning/relearning this you have skipped a couple easy steps for understanding. Here's a simpler example to start with.
public abstract class Shape
{
public abstract double GetArea();
public abstract double Circumference();
}
public class Square: Shape
{
public double width {get; set;}
public override double GetArea()
{
return width * width;
}
public override Circumference()
{
return width * 4;
}
}
You can now instantiate a Square or create a Circle Class and be able to use either where you use Shape.

Using same type with a class definition where keyword

I have seen this kind of definition in a library I'm using. I got crazy about the where TObjectType: CSObject. It is obvious that It seems I can use the same time in the constraint because it works and compiles but what does this really mean?
public class CSList<TObjectType>: CSList, IList<TObjectType>, IList
where TObjectType: CSObject<TObjectType>
It means that the TObjectType here must inherit from CSList<TObjectType>.
Usually you use this construct to get typed methods and properties on the base class that adjust to the actual derived classes you intend to use.
To declare such a derived class:
public class SomeDerivedClass : CSList<SomeDerivedClass>
Example:
public class Base<T>
{
public T[] Values { get; set; }
}
public TestCollection : Base<TestCollection>
{
// here, Values inherited from Base will be:
// public TestCollection[] Values { get; set; }
}
public OtherCollection : Base<OtherCollection>
{
// here, Values inherited from Base will be:
// public OtherCollection[] Values { get; set; }
}

Decorator pattern wasting memory

I have this base class having the following interface:
abstract class Base
{
abstract public object Val
{
get;
}
}
For any derived classes, Val's value must be specified at object creation time.
The question is: How can I make a derived class do this (hopefully at compile time)?
I tried adding a constructor:
abstract class Base
{
public Base(object value)
{
val = value;
}
private object val;
...
}
But as you can see then I had to declare a private field to store value in it (because Value is read-only).
The problem arises because I want to add some kind of effect to derived classes using the Decorator/Wrapper pattern introduced in GoF Design Patterns. But because I have declared the field inside Base class, the decorators keep saving a copy of the same data and I end up wasting memory.
Try this instead:
abstract class Base
{
public Base(object val)
{
this.Val = val;
}
public object Val { get; private set; }
}
That way, your derived class doesn't need its own field:
public class Derived : Base
{
public Derived(object val) : base(val) { }
}
If it is a decorator, then don't have a field:
public override object Val {
// add any decoration effects here if needed
get { return tail.Val; }
}
Where tail is the thing you are decorating.
However, it sounds like you mean inheritance (not decoration) - if so:
abstract class BaseClass {
protected BaseClass(object val) {...}
}
class ConcreteType : BaseClass {
public ConcreteType(object val)
: base(val) { }
}
Here the base class could even handle the storage etc.

Categories