I have the following "models":
My base class:
public abstract class Search : Model
{
//Properties ...
public void ShallowCopy(Search reference)
{
base.ShallowCopy(reference);
//Do stuff
}
}
My inheriting class:
public class Vehicle : Search
{
//Properties
public void ShallowCopy(Vehicle reference)
{
base.ShallowCopy(reference);
//Do stuff
}
}
My base "viewModel" is generic:
public abstract class MasterDataWithoutAddressViewModel<TPrimaryModel> : MasterDataViewModel<TPrimaryModel>
where TPrimaryModel : Search, new()
{
public void JustAMethod()
{
//do stuff
foreach (TPrimaryModel primaryModel in primaryModels)
{
TPrimaryModel primaryModelCopy = new TPrimaryModel();
primaryModelCopy.ShallowCopy(primaryModel);
//Do more stuff
}
}
}
My inheriting "viewModel":
public class VehicleViewModel : MasterDataWithoutAddressViewModel<Vehicle>
{
//...
}
With primaryModelCopy.ShallowCopy(primaryModel); I expected the ShallowCopy of Vehicle to be called. However just the method of the base class Search is called. Debugger shows that primaryModel and primaryModelCopy are both from the correct type (Vehicle).
This is the complete inheritance hierarchy of my "models":
This happens because you have a compile time collision (due to the way overload resolution behaves) between methods with the same signature in your base and derived classes.
You need to declare your method virtual, and override them in derived classes:
Base:
public virtual void ShallowCopy(Search reference)
{
base.ShallowCopy(reference);
//Do stuff
}
Derived:
public override void ShallowCopy(Search reference)
{
base.ShallowCopy(reference);
//Do stuff
}
Overload resolution is performed at compile-time, and in JustAMethod it's performed once, not once per type-argument. So primaryModelCopy.ShallowCopy is resolved to the Search.ShallowCopy method.
There are two options here:
You could use normal polymorphism, making Search.ShallowCopy virtual, and overriding it in Vehicle.ShallowCopy (which would need to cast the parameter back to Vehicle in the method)
You could use dynamic typing in JustAMethod to perform overload resolution at execution-time instead. (This doesn't feel like a good idea to me, but it's an option.)
Related
I have a base class (can also be an interface) and n-classes that extend the base class.
I want to have a function that excepts only classes of the base class type.
Currently I am doing something like this
abstract class BaseClass{
public abstract void Execute();
}
class MyClass : BaseClass {
public void Execute(){
//my code
}
}
[...]
MyFunction(Type param)
{
//check if param is type of BaseClass. If not, throw exception
}
The problem with this implementation is, that I can pass any type of class. My goal is to prevent this.
Like in TypeScript you can do this
myFunction(param: {new (): BaseClass}){
//my code
}
Is there a similar approach I can use in C#?
There's a couple of things you can do, depending on what you actually want to do in the function.
Stating your actual use case makes it easier to come up with a solution.
Looking at the typescript code it looks like you want to be able to call the constructor inside the function to produce an instance of the given type that derives from BaseClass.
In this case I'd try using generics:
public void MyFunction<T>() where T: BaseClass, new()
{
T myClass = new T();
//Do stuff...
}
This works with interfaces/classes. It will only accept types deriving from BaseClass.
Edit: updated my answer after being notified how my previous answer wouldn't know if it was a grandchild of the base class
public abstract class BaseClass
{
public abstract void Test();
}
public class DerivedFromBase : BaseClass
{
public override void Test(){}
}
public class Grandchild : DerivedFromBase
{
}
public class Main
{
Grandchild aClass= new Grandchild(); // Instantiate Normally
UseIfOnlyTypeOfBaseClass(aClass);// Use Method with check like this
}
private void UseIfOnlyTypeOfBaseClass<T>(T param)
{
if (typeof(T).IsSubclassOf(typeof(BaseClass)))
{
Console.WriteLine("Match");
}
}
My abstract class has a method that is abstract like this:
public abstract void Run(BaseType baseType);
And now in my derived class which has to implement this function, i want it to only accept a specific derived type from BaseType
So it would have:
public override void Run(DerivedType derivedType){}
Is there any way to enforce this at all ?
Currently i have to do:
public override void Run(BaseType baseType) {
if(!(baseType is DerivedType)) {
// throw exception
}
}
It's not very strict with enforcing the type - i was wondering if there is a way to do so without the need to constantly add a type check ?
I've sometimes used this pattern:
public interface IHandler
{
void Run();
}
public abstract class BaseHandler<TObj> : IHandler
where TObj: BaseType
{
protected readonly TObj _obj {get;set;}
public BaseHandler(TObj obj)
{
this._obj = obj;
}
public abstract void Run();
}
public class DerivedHandler : BaseHandler<DerivedType>
{
public DerivedHandler(DerivedType obj) : base(obj)
{
}
public override void Run()
{
// do stuff with base._obj
}
}
public class HandlerService
{
public IHandler CreateHandler<TObj>(TObj obj)
{
// Depending on your DI container, you could resolve this automatically from the container
if (typeof(TObj) == typeof(DerivedType))
{
return new DerivedHandler(obj);
}
throw new NotImplementedException();
}
}
This allows you to define a specific "handler" for each derived type, and then access it through a common interface.
The idea is that you instantiate a specific handler for the object, and then methods like Run() operate on that object. You can then resolve a handler through the service.
I'll fill in some more info later when I have time.
You want the language to do something that it really shouldn't. You want a covariant argument, which violates the Liskov Substitution Principle: It makes the implementation of the abstract class not usable in every situation where the abstract base class is usable. This is the whole point of abstract base classes to begin with.
Although it could make sense to have a covariant return type (returning a more derived type then the abstract methods specifies) the language also prevents you to do that.
Generic class is base class, and a member method uses generic data type, how will you make the method of derived accept integers instead of generic data type?
You can do something like this -
public class MyBaseClass<T>
{
public virtual void MyMethod(T typeT)
{
//some important functionality
}
}
public class MyChildClass : MyBaseClass<int>
{
public override void MyMethod(int typeInt)
{
//Do your stuff
//and if you would like to call base method, use the following-
base.MyMethod(typevar);
}
}
abstract class A<T> where T:A<T>
{
public event Action<T> Event1;
}
class B : A<B>
{
//has a field called Action<B> Event1;
}
Is there a more elegant way to do this? I want stuff (events, etc) in the base class to be able to use the subclass' type.
The pattern you are using does not actually implement the constraint you want. Suppose you want to model "an animal can only be friendly with something of its own kind":
abstract class Animal<T> where T : Animal<T>
{
public abstract void GetFriendly(T t);
}
class Cat : Animal<Cat>
{
public override void GetFriendly(Cat cat) {}
}
Have we succeeded in implementing the desired constraint? No.
class EvilDog : Animal<Cat>
{
public override void GetFriendly(Cat cat) {}
}
Now an evil dog can be friendly with any Cat, and not friendly with other evil dogs.
The type constraint you want is not possible in the C# type system. Try Haskell if you need this sort of constraint enforced by the type system.
See my article on this subject for more details:
http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx
What you have works very well. In fact it's very similar to other .NET interfaces and types where you want the interface implementer to use your type, like:
public class MyClass : IEqualityComparer<MyClass>
{
// From the interface IEqualityComparer
public bool Equals(MyClass other) { ... }
...
}
I don't think you need to specify where T:A.
T will be B when you use class B:A
This is also known as CRTP or Curiously recurring template pattern and is a known idiom.
Since A is abstract, you can add abstract methods to A and invoke them from A and B, which will be forced to implement the method, will be the invoker:
abstract class A<T> where T:A
{
public event Action<T> Event1;
public abstract void Method();
public A(){Method();}
}
class B : A<B>
{
//has a field called Action<B> Event1;
public void Method(){ //stuff }
}
On instantiation of B, the base class constructor will call Method() which is only implemented in B, forcing B's instance to be called.
This allows A to invoke subclass specific methods without requiring A to have specific knowledge of Children. The downside is that ALL children must implement Method or re-abstract it to their own children.
My most recent question was marked as a duplicate of this one. I totally agree on that matter. So I came here to take a look at the answers and to read Eric's post on that (very interesting indeed). You can not enforce this at compile time with the type system but you can do this at runtime. The way I implemented this is:
abstract class FooBase<T>
{
protected FooBase()
{
if (typeof(T) != GetType())
{
throw new InvalidOperationException();
}
}
}
By doing this we can plant the seed of an evil dog, but that dog will be aborted at runtime.
Let's say I have a class library that defines a couple entity interfaces:
public interface ISomeEntity { /* ... */ }
public interface ISomeOtherEntity { /* ... */ }
This library also defines an IRepository interface:
public interface IRepository<TEntity> { /* ... */ }
And finally, the library has an abstract class called RepositorySourceBase (see below), which the main project needs to implement. The goal of this class is to allow the base class to grab new Repository objects at runtime. Because certain repositories are needed (in this example a repository for ISomeEntity and ISomeOtherEntity), I'm trying to write generic overloads of the GetNew<TEntity>() method.
The following implementation doesn't compile (the second GetNew() method gets flagged as "already defined" even though the where clause is different), but it gets at what I'm trying to accomplish:
public abstract class RepositorySourceBase // This doesn't work!
{
public abstract Repository<TEntity> GetNew<TEntity>()
where TEntity : SomeEntity;
public abstract Repository<TEntity> GetNew<TEntity>()
where TEntity : SomeOtherEntity;
}
The intended usage of this class would be something like this:
public class RepositorySourceTester
{
public RepositorySourceTester(RepositorySourceBase repositorySource)
{
var someRepository = repositorySource.GetNew<ISomeEntity>();
var someOtherRepository = repositorySource.GetNew<ISomeOtherEntity>();
}
}
Meanwhile, over in my main project (which references the library project), I have implementations of ISomeEntity and ISomeOtherEntity:
public class SomeEntity : ISomeEntity { /* ... */ }
public class SomeOtherEntity : ISomeOtherEntity { /* ... */ }
The main project also has an implementation for IRepository<TEntity>:
public class Repository<TEntity> : IRepository<TEntity>
{
public Repository(string message) { }
}
And most importantly, it has an implementation of the abstract RepositorySourceBase:
public class RepositorySource : RepositorySourceBase
{
public override IRepository<ISomeEntity> GetNew()
{
return new (IRepository<ISomeEntity>)Repository<SomeEntity>(
"stuff only I know");
}
public override IRepository<ISomeOtherEntity> GetNew()
{
return new (IRepository<ISomeEntity>)Repository<SomeOtherEntity>(
"other stuff only I know");
}
}
Just as with RepositorySourceBase, the second GetNew() method gets flagged as "already defined".
So, C# basically thinks I'm repeating the same method because there's no way to distinguish the methods from their parameters alone, but if you look at my usage example, it seems like I should be able to distinguish which GetNew() I want from the generic type parameter, e.g, <ISomeEntity> or <ISomeOtherEntity>).
What do I need to do to get this to work?
Update
I ended up solving this using specifically-named methods and a Func<T, TResult> parameter.
So, RepositorySourceBase now looks like this:
public abstract class RepositorySourceBase
{
public abstract Repository<ISomeEntity> GetNewSomeEntity();
public abstract Repository<ISomeOtherEntity> GetNewSomeOtherEntity();
}
And RepositorySource looks like this:
public class RepositorySource : RepositorySourceBase
{
public override IRepository<ISomeEntity> GetNewSomeEntity()
{
return new (IRepository<ISomeEntity>)Repository<SomeEntity>(
"stuff only I know");
}
public override IRepository<ISomeOtherEntity> GetNewSomeOtherEntity()
{
return new (IRepository<ISomeEntity>)Repository<SomeOtherEntity>(
"other stuff only I know");
}
}
Now, what started this whole thing off was that I needed a generic RepositoryUtilizer class that could grab a repository from a source simply by knowing the type of repository (which could be specified as a generic type parameter). Turns out, that wasn't possible (or at least not easily possible). However, what is possible is to use the Func<T, TResult> delegate as a parameter to allow the RepositoryUtilizer class to obtain the repository without needing to "know" the method name.
Here's an example:
public class RepositoryUtilizer
{
public DoSomethingWithRepository<TEntity>(
Func<TRepositorySource, IRepository<TEntity>> repositoryGetter)
{
using (var repository = repositoryGetter(RepositorySource))
{
return repository.DoSomething();
}
}
}
}
You cannot get this work as you intended. Type constraints cannot be used to decide between your two methods.
public abstract Repository<TEntity> GetNew<TEntity>()
where TEntity : SomeEntity;
public abstract Repository<TEntity> GetNew<TEntity>()
where TEntity : SomeOtherEntity;
Assume
public class SomeEntity { }
public class SomeOtherEntity : SomeEntity { }
and SomeOtherEntity is a valid type argument for both methods yielding two methods with identical signature.
The way to go is probably a single generic method that uses the supplied type argument to dispatch the call to the desired implementation. This is in turn probably solved most easily by implementing an interface on all concrete types.
Constraints are not part of the signature. This fact has numerous ramifications, many of which apparently irk people to no end. For some of those ramifications, and about a million comments telling me that I am WRONG WRONG WRONG, see this article and its accompanying comments.
http://blogs.msdn.com/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx
I would solve your problem by having two methods with two different names.
The only solution I can think of is to define an IRepositorySource<T> interface that each RepositorySource class can implement explicitly:
public interface IRepositorySource<T>
{
IRepository<T> GetNew();
}
public class RepositorySource : IRepositorySource<ISomeEntity>, IRepositorySource<ISomeOtherEntity>
{
IRepository<ISomeEntity> IRepositorySource<ISomeEntity>.GetNew()
{
...
}
IRepository<ISomeOtherEntity> IRepositorySource<ISomeOtherEntity>.GetNew()
{
...
}
}
To access these methods you'll need to cast a RepositorySource instance into the required interface type e.g.
IRepository<IEntity> r = ((IRepositorySource<IEntity>)repositorySource).GetNew();
public class RepositorySource
{
static IRepository<T> IRepositorySource.GetNew<T>()
{
if (typeof(T) == typeof(ISomeEntity))
return (IRepository<T>)new SomeEntityRepository();
...
}
}