0

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?

Anton Voronin
  • 98
  • 1
  • 6
  • 5
    Why would you want to do that? – Philippe Feb 22 '17 at 13:46
  • You can't. You can check the type at runtime and throw an exception, but nothing the compiler can prevent – pinkfloydx33 Feb 22 '17 at 13:46
  • 3
    What you ask for is against object oriented programming, ***MyDerivedClass** IS **MyClass***. It's the same as "I don't want a car, but I want a Ferrari!" – Esko Feb 22 '17 at 13:50
  • @Esko,thank you. this is a useful remark for me because I wasn't sure if I was doing the right thing. My problem is simple: I have a class and a derived class which both share the same functionality but instances of those classes are stored in different databases and I would like to have different methods for manipulating content there instead of choosing proper database depending on the type of instance of a class – Anton Voronin Feb 22 '17 at 13:57
  • @Esko Your analogy is reversed. It's like saying, "I'll accept any kind of car that exists, but I don't accept Ferraris." – Servy Feb 22 '17 at 14:20

2 Answers2

1

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");
       }
  }
}
Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
  • While I wouldn't recommend what OP wants (for the same reason as the comments on the question), this is the correct approach to satisfy the OPs (uncommon) request. – casperOne Feb 22 '17 at 13:58
  • should I mark this answer as the correct one if this is considered as not recommended practice? – Anton Voronin Feb 22 '17 at 14:01
  • @AntonVoronin if it is answering the asked question and the answer solves that particular problem, then there is no harm in accepting it :) – Ehsan Sajjad Feb 22 '17 at 14:15
1

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

Community
  • 1
  • 1
Zinov
  • 3,817
  • 5
  • 36
  • 70