Here's the situation. I have a class and a derived class
public class MyClass
{ }
public class MyDerivedClass : MyClass
{ }
And also I have a method (in an external class) which takes an instance of MyClass as a parameter:
public class AnotherClass {
public void DoSomething(MyClass myClass)
{ }
}
How can I restrict DoSomething method to accept instances of MyClass only, but not instances of MyDerivedClass?
If that's what you want then you would need to check in code yourself that if it is a Derived type through Exception to tell the calling code that Derived type objects are not allowed for this method:
public class AnotherClass {
public void DoSomething(MyClass myClass)
{
if(myClass.GetType() != typeof(MyClass))
{
throw new Exception("Derived objects not allowed");
}
}
}
What are you trying to do here is more related to an Invariance problem that is pretty common on all programming languages.
Means that you can use only the type originally specified; so an
invariant generic type parameter is neither covariant nor
contravariant. You cannot assign an instance of IEnumerable
(IEnumerable) to a variable of type
IEnumerable or vice versa.
Here is the reference for you https://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx
My advice, try to change the implementation and put all the methods into an interface, that should be more clear
class Root: Interface
{
...implementation of your common methods
}
class Derived: Interface
{
...implementation of your common methods
//this should just
public void DoSomething(MyClass myClass)
}
If you don't want to use the above approach then use the "as" operator to treat the parameter that you are passing as MyRootClass, var a = parameter as MyRootClass. If a is null then you are not passing the correct value to the method, or check for the type directly.
If would recommend that you read this topics:
http://amapplease.blogspot.com/2009/04/invariance-covariance-contravariance.html
https://stackoverflow.com/a/13107168/819153
https://blogs.msdn.microsoft.com/ericlippert/2009/03/19/representation-and-identity/
Hope this helps
Related
I have problem as above. My code:
public abstract class BaseFactory<T> where T: class
{
protected static dbModelContainer context = new dbModelContainer();
public static int UpdateDataBase_static()
{
return context.SaveChanges();
}
}
and my question is how can I call
BaseFactory.UpdateDataBase_static();
instead of:
BaseFactory<SomeClass>.UpdateDataBase_static();
Any ideas?
You can't, because there is no such method. The closest is to have a non-generic base that the generic class inherits from. Then you can have a method there that doesn't depend on the parameterising type.
To call BaseFactory.UpdateDataBase_static(); you need a class BaseFactory. Inherite the generic BaseFactory<T> from it.
public abstract class BaseFactory
{
protected static dbModelContainer context = new dbModelContainer();
public static int UpdateDataBase_static()
{
return context.SaveChanges();
}
}
public abstract class BaseFactory<T>:BaseFactory where T: class
{
....
}
You don't.
You always need to supply the generic type arguments when accessing a class, even though you aren't using that type argument in your method. Since you don't actually use the generic type in the method it means you could move that method out of that class, and into one that isn't generic, but for as long as it's in that class you'll need to supply the generic argument.
It's not possible to do exactly what you're asking, but since the method doesn't use T at all, you can just use BaseFactory<object>.UpdateDataBase_static(); without specifying any particular class.
But as an editorial comment, in general a method in a generic class that never uses the generic parameter probably shouldn't be there.
I am trying to implement IEnumerable<Turtle> in a class deriving from a base class that already implements IEnumerable<Animal>.
Why will calling base.Cast<Turtle>() (or any LINQ method on the base element) in any method from the class Turtle fail to compile?
It is not possible to replace base with this as it obviously results in a StackOverflowException.
Here is a minimal code sample to replicate the issue:
public interface IAnimal {}
public class Animal : IAnimal {}
public class Turtle : Animal {}
public class AnimalEnumerable : IEnumerable<Animal> {
List<Animal> Animals = new List<Animal>();
IEnumerator<Animal> IEnumerable<Animal>.GetEnumerator() {
return Animals.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return Animals.GetEnumerator();
}
}
public class TurtleEnumerable : AnimalEnumerable, IEnumerable<Turtle> {
IEnumerator<Turtle> IEnumerable<Turtle>.GetEnumerator() {
return base.Cast<Turtle>().GetEnumerator(); //FAILS WITH "CANNOT RESOLVE SYMBOL Cast"
}
}
For some reason, replacing base.Cast<Turtle>().GetEnumerator(); with this.OfType<Animal>().Cast<Turtle>().GetEnumerator(); works without throwing a StackOverflowException, but I have no idea why.
There are numerous problems with the code given that other answers get into. I want to answer your specific question:
Why will calling base.Cast<Turtle>() (or any LINQ method on the base element) in any method from the class Turtle fail to compile?
Let's go to the specification, section 7.6.8.
A base-access is used to access base class members that are hidden by similarly named members in the current class or struct.
Are you accessing a base class member? NO. An extension method is a member of the static class that contains the extension method, not the base class.
A base-access is permitted only in the block of an instance constructor, an instance method, or an instance accessor.
You're fine here.
When base.I occurs in a class or struct, I must denote a member of the base class of that class or struct.
Again, Cast<T> is not a member of the base class.
When a base-access references a virtual function member (a method, property, or indexer), the determination of which function member to invoke at run-time (ยง7.5.4) is changed.
You are not accessing a virtual anything. Extension methods are static.
The function member that is invoked is determined by finding the most derived implementation of the function member with respect to B (instead of with respect to the run-time type of this, as would be usual in a non-base access). Thus, within an override of a virtual function member, a base-access can be used to invoke the inherited implementation of the function member.
So now we see what the purpose of a base access is: to enable a non-virtual dispatch to a virtual member that was overriden in the current type, or to call a base class member that was hidden by a new member in the current type. That is not what you are trying to use base for, and therefore you are doomed to failure. Stop using base off-label like this. Only use it when attempting to do a non-virtual dispatch to a virtual member, or get access to a hidden member.
Eric Lippert has stated before that this was a somewhat conscious design decision here. You were never meant to use extension methods in a case where you have access to the implementation of your base class in the first place.
And if you think about it, you also dont need to do this here. Make a GetEnumerator property or method that is protected and use it! Basic object orientation; no need to torture linq here.
EDIT:
It was pointed out that my previous suggestion did not work. So let me suggest just not implementing two different IEnumerable interfaces as this will cause a lot of headaches with foreach anyway.
I have come to believe that this implementation might be what you actually want:
public interface IAnimal { }
public class Animal : IAnimal { }
public class Turtle : Animal { }
public class AnimalEnumerable : IEnumerable<Animal>
{
IEnumerator<Animal> IEnumerable<Animal>.GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
public class TurtleEnumerable : AnimalEnumerable
{
}
You can then enumerate through Animal and their derivatives all the like
There are several issues with your approach. TurtleEnumerable implements both IEnumerable<Animal> and IEnumerable<Turtle>. To be able to use a TurtleEnumerable instance in a foreach loop you will have to cast it for the code to compile:
foreach (var turtle in (IEnumerable<Turtle>) turtleEnumerable)
You are also using explicit interface implementations to hide the generic GetEnumerator() methods. You have to do that because you cannot do overload resolution on return type alone and the two generic GetEnumerator() methods only differ by return type.
However, this means that a TurtleEnumerable method cannot call the base GetEnumerator() method. The reason for this is that base does not behave like a variable of type "base". Instead it is a reserved word that only can be used to call base class methods. A corollary to this is that extension methods cannot be used with base. Also, you cannot cast base so explicit interface implementations on the base class are not callable through base.
However, you can cast this but because the generic GetEnumerator() on TurtleEnumerable hides the generic GetEnumerator() on AnimalEnumerable you will not be able to call into the base class so you will get a stack overflow because at some point the implementation of TurtleEnumerable.GetEnumerator() will call the same GetEnumerator.
To make your code compile you need to create a protected IEnumerator<Animal> GetEnumerator() method in your base class and create your own TurtleEnumerator class that wraps the base enumerator instance you can get by calling the protected method.
public class TurtleEnumerable : AnimalEnumerable, IEnumerable<Turtle> {
IEnumerator<Turtle> IEnumerable<Turtle>.GetEnumerator() {
return new TurtleEnumerator(base.GetEnumerator());
}
sealed class TurtleEnumerator : IEnumerator<Turtle> {
IEnumerator<Animal> animalEnumerator;
public TurtleEnumerator(IEnumerator<Animal> animalEnumerator) {
this.animalEnumerator = animalEnumerator;
}
public Turtle Current {
get { return (Turtle) animalEnumerator.Current; }
}
Object IEnumerator.Current {
get { return Current; }
}
public Boolean MoveNext() {
return animalEnumerator.MoveNext();
}
public void Reset() {
animalEnumerator.Reset();
}
public void Dispose() {
animalEnumerator.Dispose();
}
}
}
All in all having a collection the implements both IEnumerable<Base> and IEnumerable<Derived> will get you into a lot of trouble. What are you trying to achieve by using this design?
Using a generic List<T> and contravariance you can do things like this:
IEnumerable<Turtle> turtles = new List<Turtle>();
IEnumerable<Animal> animals = (IEnumerable<Animal>) turtles;
You can also replace List<T> by your own generic collection type if that is required.
I will answer to that question:
Why will calling base.Cast() (or any LINQ method on the base
element) in any method from the class Turtle fail to compile?
The reason of that exception is Cast and other such methods are extension methods. And extension methods are static.
For example, let's look at that:
public static class Extensions
{
public static void Method2(this Base b) ...
}
public class Base
{
public void Method1() ...
}
public class Derived:Base
{
public void Test()
{
base.Method1();
base.Method2(); // Does not contain a definition
}
}
And as you know extension methods are a really nice syntactic sugar. They're not really added to the class, but the compiler makes it feel like they are. So, compiler will change that line of code to that one:
Extensions.Method2(base);
If you replace your code with that one the compiler will give more appropriate error message: Use of keyword base is not valid in this context.
As said in MSDN:
A base class access is permitted only in a constructor, an instance
method, or an instance property accessor.
Why are you implementing the IEnumerable on the TurtleEnumerator class? Also, I don't think the accessibility on the AnimalEnumerable when you implemented the IEnumerable interface is correct.
Wouldn't it be implemented something like this:
public interface IAnimal { }
public class Animal : IAnimal { }
public class Turtle : Animal { }
public class AnimalEnumerable : IEnumerable<Animal>
{
protected List<Animal> Animals = new List<Animal>();
public IEnumerator<Animal> GetEnumerator()
{
return Animals.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return Animals.GetEnumerator();
}
}
public class TurtleEnumerable : AnimalEnumerable
{
public void AddTurtle(Turtle turtle)
{
Animals.Add(turtle);
}
public IEnumerable<Turtle> GetTurtles()
{
var iterator = GetEnumerator();
yield return iterator.Current as Turtle;
}
}
[Test]
public void CanAddTurtles()
{
Turtle one = new Turtle();
Turtle two = new Turtle();
TurtleEnumerable turtleStore = new TurtleEnumerable();
turtleStore.AddTurtle(one);
turtleStore.AddTurtle(two);
foreach (var turtle in turtleStore.GetTurtles())
{
// Do something with the turtles....
}
}
public abstract class A
{
// constructors omitted
public abstract A Create(SomeData data);
}
public class B : A
{
// constructors omitted
public override A Create(SomeData data)
{
return new B(data);
}
}
What I want is to be able to make the Create method static, so that I can get an instance of B without having to create a useless instance with an empty constructor. (If you're wondering why, A is actually a generic type of the form A<TFoo, TBar>, where TBar corresponds to the derived types. As we all know, you can't instantiate a generic type using a constructor that takes any arguments.)
I am already aware that static methods are decoupled from the object hierarchy, only relying on the name of the type. That means I can't have Create as an abstract method that I force all descendants to implement. Is there another way I can implement this pattern?
Something like this might work, depends on your requirements
public abstract class A
{
public string Data { get; set; }
public static T Create<T>(string data) where T : A, new()
{
return new T() { Data = data };
}
}
public class B : A { }
then can do
A foo = A.Create<B>("foo");
There is simply no way to do this. Inheritance is based off of instance methods in C# and has no equivalent feature for static methods. Another way to implement this pattern though is to require a lambda in lieu of a static method.
For example (you mentioned the actual type was A<TFoo, TBar>)
void UseIt<TFoo, TBar>(A<TFoo, TBar> p, Func<SomeData, TBar> func) {
TBar b = func();
...
}
The consumer doesn't care if Create is static, instance or even called create. Generally all they care about is having a function which takes a SomeData and returns a TBar. Delegates fit this pattern exactly.
In C++, you can invoke method's from a template argument like so:
template<class T> class foo
{
T t;
t.foo();
}
But in C#, it looks like this is not possible:
class foo<T>
{
T t;
public void foo() {
t.foo(); // Generates a compiler error
}
};
I suppose this probably isn't possible in C#, is it?
You have discovered the difference between templates and generics. Though they look similar they are in fact quite different.
A template need be correct only for the type arguments that are actually provided; if you provide a T that does not have a method foo then the compilation fails; if you provide only type arguments that have a foo then compilation succeeds.
By contrast a generic must be correct for any possible T. Since we have no evidence that every possible T will have a method foo then the generic is illegal.
Yes, if you know that the generic type placeholder T implements a member from a base class or interface, you can constrain the type T to that base class or interface using a where clause.
public interface IFooable
{
void Foo();
}
// ...
public class Foo<T> where T : IFooable
{
private T _t;
// ...
public void DoFoo()
{
_t.Foo(); // works because we constrain T to IFooable.
}
}
This enables the generic type placeholder T to be treated as an IFooable. If you do not constrain a generic type placeholder in a generic, then it is constrained to object which means only object's members are visible to the generic (that is, you only see members visible to an object reference, but calling any overridden members will call the appropriate override).
Note: This is additionally important because of things like operator overloading (remember that operators are overloaded, not overridden) so if you had code like this:
public bool SomeSuperEqualsChecker<T>(T one, T two)
{
return one == two;
}
This will always use object's == even if T is string. However, if we had:
public bool SomeSuperEqualsChecker<T>(T one, T two)
{
// assume proper null checking exists...
return one.Equals(two);
}
This WOULD work as expected with string because Equals() is overridden, not overloaded.
So, the long and the short is just remember that an unconstrained generic placeholder does represent any type, but the only calls and operations visible are those visible on object.
In addition to interface/base class constraints, there are a few other constraints:
new() - Means that the generic type placeholder must have a default constructor
class - Means that the generic type placeholder must be a reference type
struct - Means that the generic type placeholder must be a value type (enum, primitive, struct, etc)
For example:
public class Foo<T> where T : new()
{
private T _t = new T(); // can only construct T if have new() constraint
}
public class ValueFoo<T> where T : struct
{
private T? _t; // to use nullable, T must be value type, constrains with struct
}
public class RefFoo<T> where T : class
{
private T _t = null; // can only assign type T to null if ref (or nullable val)
}
Hope this helps.
You need to add a type constraint to your method.
public interface IFoo {
void Foo();
}
public class Foo<T> where T : IFoo {
T t;
public void foo() {
t.Foo(); // Generates a compiler error
}
}
It is possible if you are willing to accept generic type constraints. This means that your generic type must be constrained to derive from some base class or implement some interface(s).
Example:
abstract class SomeBase
{
public abstract DoSomething();
}
// new() ensures that there is a default constructor to instantiate the class
class Foo<T> where T : SomeBase, new()
{
T t;
public Foo()
{
this.t = new T();
this.t.DoSomething(); // allowed because T must derive from SomeBase
}
}
When i need to pass a Generic Type I can use the Syntax
(Example : Ofcourse it is not a Generic Method)
public void Sample(T someValue)
{
......
}
What is the benefit of declaring Sample<T> ?
I mean
public void Sample<T> (T someValue)
{
......
}
Generic types and generic methods are very different things. It sounds like you have a generic type:
class SomeType<T> {
public void Sample(T someValue) {...}
}
and are discussing having a generic method inside it:
class SomeType<T> {
public void Sample<T>(T someValue) {...}
}
These are very different. In the first, inside Sample, then T means "the T that got passed to SomeType<T>". In the second, inside Sample, this is a separate and independent T - "the T that got passed to Sample<T>". In fact, calling it T (in this case) is a mistake. You could have, for example:
var obj = new SomeType<int>(); // here T for SomeType<T> is int
obj.Sample<decimal>(123.45M); // here T for Sample<T> is decimal
Note that there is no easy way (within Sample<T>) of saying "the T in SomeType<T>" - hence why you should rename the method's generic type parameter.
There are valid scenarios for this type of scenario (generic methods on generic types), for example (and note the new name):
class SomeType<T> {
public void Sample<TActual>(TActual someValue) where TActual : T, new() {...}
}
This allows us to do some very interesting things in terms of inheritance, etc - or you might want a generic method that has little or no relation to T. That is fine too.
For this to work:
public void Sample(T someValue)
{
......
}
The type T has to be declared in the system already. And the method will only accept the type T or its derivatives.
By declaring this:
public void Sample<T> (T someValue)
{
......
}
you say the method will accept any type that comes.
Consider the following:
class SomeClass<T>
{
public void Sample(T value)
{
// code goes here
}
}
or this:
class SomeClass
{
public void Sample<T>(T value)
{
// code goes here
}
}
In the first case, for all calls to Sample in a specific instance T will be the same type. In the second case each call in a specific instance can have its own type of T, since the generic type argument is supplied with the method call.
The second approach can have many uses, but one that I have used myself sometimes is in factory methods:
public static class SomeFactory
{
public static T CreateSomeObject<T>()
{
T result = Activator.CreateInstance<T>();
// perform any extra initialization
return result;
}
}
You can use the 2nd example if your class isn't generic. It means you can make just that method generic. If your class is generic, you should use your 1st example.