"where T : class" VS regular class in an extention method - c#

I would like a technical difference between the following two Extension method declarations and when you would use one over the other:
public static void DoSomething(this MyClass theObject)
vs
public static void DoSomething<T>(this T theObject) where T : MyClass
For example, I know there is a difference when using this with an object of a class that inherits from MyClass class but I don't know why.

Assume this implementation:
public static List<T> DoSomething<T>(this T theObject) where T : MyClass
=> new List<T>();
Invoked as
MyChildClass x; // MyChildClass : MyClass
var list = DoSomething(x);
// list is an instance of List<MyChildClass>, instead of List<MyClass>
Use first (non-generic) when you don't need to know the "actual"
(child) type.
Use second (generic) when you plan to use the "actual" type in
further generic code.
I see it as a "smell" when someone designs a class/function as generic, even though it "doesn't need to be" generic = the base type would suffice. (Equivalent 'generic' impl is somewhat more difficult to read)

Related

Restrict passing instances of derived classes as method parameters

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

How can a class inherit from a parameterized version of itself?

I saw a C# class SomeClass that was defined like
public class SomeClass : IComparable<SomeClass>, IEquatable<SomeClass>
{
// ...
}
and I'm wondering how to translate that into English. The way I understand it seems logically impossible. How can a class inherit from a parameterized version of itself? Also, is this a common design pattern?
The key is to recognize that it's not inheriting from (or implementing) a parameterized version of itself, but rather inheriting from (or implementing) another class or interface, and using itself as a generic parameter for that target type.
For example, IComparable<T> says that there will be a CompareTo() method that takes an object of type T as a parameter. So by implementing IComparable<SomeClass> you're simply guaranteeing that a method with that signature will exist on this class:
public class SomeClass : IComparable<SomeClass>
{
public int CompareTo(SomeClass other)
{
//...
}
}
And yes, this is fairly common practice. Classes often implement the generic IComparable<> and IEquatable<> interfaces to show that they can be compared with other items of the same type. It's maybe also worth mentioning that enums in Java are declared as extending Enum<> of themselves--a pattern which is not common in C#, but does appear from time to time.
Translated in "English" it means: "Boy (or girl), you'd better be type-safe when implementing those interfaces, especially IComparable. Otherwise, you'll have to perform type casting, which I guess you don't want"
See the code below. SomeClass implemented IComparable and IComparable.
See differencies between implementations of CompareTo(object) and CompareTo(SomeClass).
namespace InterfacesStuff
{
internal class Program
{
private static void Main(string[] args)
{
var someClass1 = new SomeClass {ComparedValue = 1};
var someClass2 = new SomeClass {ComparedValue = 2};
//someClassObject defined as SomeClass
//object someClassObject = new SomeClass { ComparedValue = 2 };
//someClassObject defined as anything else but SomeClass
object someClassObject = 5;
int comparisonSomeClassBySomeClass = someClass1.CompareTo(someClass2);
int comparisonSomeClassByObject = someClass1.CompareTo(someClassObject);
}
}
public class SomeClass : IComparable, IComparable<SomeClass>, IEquatable<string>, IEquatable<int>,
IEquatable<double>
{
public int ComparedValue;
public int CompareTo(object obj)
{
var presumedSomeClassObject = obj as SomeClass;
if (presumedSomeClassObject != null)
{
if (ComparedValue <= ((SomeClass) obj).ComparedValue)
return -1;
}
return 0;
}
public int CompareTo(SomeClass other)
{
if (ComparedValue <= other.ComparedValue)
return -1;
return 0;
}
public bool Equals(double other)
{
throw new NotImplementedException();
}
public bool Equals(int other)
{
throw new NotImplementedException();
}
public bool Equals(string other)
{
throw new NotImplementedException();
}
}
}
It is not Inheriting, It is implementing the IComparable Interface. what is going on is
Someclass Implements the Icomparable and the IEquatable interface. Implementing an interface is like signing a contract stating you gaurentee that this class will implement the methods on an interface.
Icomparable msdn, IEquatable. If you look at the MSDN pages you can see that SomeClass gaurentees it will implement the methods in some fashion.
This is very common practice and it is many different names. The ones I hear most are programming by contract and Implementation over Inhertience. It lets you do a lot of cool things, like Dependency Injection, Proper Unit testing, better Generics. It does this because the compiler doesnt need to know the concrete class that your object is implementing. It just needs to know that it has certain functions on it. For further reading on this I would read Chapter one of the gang of four Design pattern book.
Wikipedia link Specifically the Introduction to Chapter one section
It doesn't really have to be convenient to express it in english for it to be valid code, although I'd probably read that as "SomeClass is comparable and equatable to itself". That doesn't really explain what's going on though, it's just a way of expressing it.
In C# types can be generic over categories of other types. Generic types are basically "type constructors". They take other types as parameters, and use them to construct new types. For instance, IEnumerable<int> and IEnumerable<string> are two completely different types. The non-generic version (IEnumerable) is a third one. In C# a type A can inherit ANY other type B as long as none of the following is true (I hope I didn't miss anything):
B is already a subtype of A
B is a class and A has already inherited another class
B is a struct
A is an interface but B is not
A is the same type as B
B is sealed
A is a struct and B is not an interface
This even makes the following code legal:
class Foo<T>
{
public T Value;
}
class Foo : Foo<int>
{
}
Foo and Foo<T> are different types, so there's no problem at all for one to inherit the other.
You can read more about generics here:
https://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx
And about inheritance here:
https://msdn.microsoft.com/en-us/library/ms173149.aspx
The code you posted does not inherit from any class. It is implementing certain so-called Interfaces. How to translate that snippet: "I guarantee that SomeClass will be Comparable and equatable with other SomeClass instances. I will provide definitions in this class on how to do that."
About specializing a class from some other class...
What you can do is something like this:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Pet
{
protected string name;
public Pet(String name)
{
this.name = name;
}
}
class Dog : Pet
{
private List<String> tricks;
public Dog(String name, List<String> tricks):base(name)
{
this.tricks = tricks;
}
}
class Program
{
static void Main(string[] args)
{
List<string> tricks = new List<string>();
tricks.Add("sit");
tricks.Add("jump");
tricks.Add("bark");
Dog puppy = new Dog("Fido", tricks);
}
}
}
Dog inherits from Pet. Dog calls Pet's constructor at creation. Whatever name you pass into Dog constructor, it will forward it to Pet constructor.
Because what happens is that a subclass first calls the constructor of its superclass with the appropriate arguments. Then it runs its own constructor. Whatever is declared as public or protected in a class will be visible to its subclasses.
Therefore Dog will have name and also a list of tricks:
You achieve this kind of view with the "Locals" window.
I recommend that you read some tutorials on c# inheritance, interfaces and generics

What is the purpose of a restricting the type of generic in a method?

I'm having a hard time understanding why it would be beneficial to do something like this: (Sample is a class)
static void PrintResults<T>(T result) where T : Sample
Wouldn't it be better to to just pass Sample into the method?
static void PrintResults (Sample result)
I recommend avoiding generic types where non-generic syntax works, such as the example you gave. However, there are other useful cases.
For example, specifying the return type generically:
static T Create<T>() where T: Sample, new()
{
return new T();
}
// Calling code
Sample sample = Create<Sample>();
instead of
static object Create()
{
return new Sample();
}
// Calling code
Sample sample = (Sample) Create();
You can also use templates to place multiple restrictions on a type. For example:
static T Create<T>() where T: IMyInterface, new()
{
return new T();
}
interface IMyInterface {}
class MyClass : IMyInterface { }
// Calling code.
MyClass myClass = Create<MyClass>();
This allows the generic creation of a new type that implements a specific interface and has a generic constructor. Also:
static void DoSomething<T>(T t) where T: IMyInterface1, IMyInterface2
{
t.MethodOnIMyInterface1();
t.MethodOnIMyInterface2();
}
interface IMyInterface1
{
void MethodOnIMyInterface1();
}
interface IMyInterface2
{
void MethodOnIMyInterface2();
}
class MyClass: IMyInterface1, IMyInterface2
{
// Method implementations omitted for clarity
}
// Calling code
MyClass myclass'
DoSomething(myclass); // Note that the compiler infers the type of T.
Where you can require multiple interfaces on a single parameter without (1) creating a new type that implements all these interfaces and (2) requiring parameters to be of that type.
As #dcastro points out in his/her answer, generic types can also tell the compiler to require types are the same. For example:
static void DoSomething<T>(T t1, T t2) where T: MyType
{
// ...
}
class MyType {}
class MyType1: MyType {}
class MyType2: MyType {}
// Calling code
MyType1 myType1;
MyType2 myType2;
DoSomething<MyType>(myType1, myType2);
Where the compiler requires that t1 and t2 are the same type but can be any type that inherits MyType. This is useful in automated unit testing frameworks, such as NUnit or MSTest, for generic equality and comparison checks.
Most of the answers are offering explanations of the usefulness of generics involving interfaces that don't really seem to address your actual question.
Truth is, for the example you posted, there is no benefit to using a generic method. It is actually worse because it will cause multiple implementations of the same function to be generated and ever slightly increase the code size at runtime.
In voids you could allways use an interface as a parameter to make multiple types work, so generics arent often useful here.
Only exceptions are the constraints on generics. And by that i dont mean something like
where T: IA, IB
since this could be done by an interface aswell that both implements IA and IB. This will get tiresome at some point however since you will need more and more interfaces. So lets look ath the "special constraints" class and new
public void AddNew(List<T> items) where T : new
{
items.Add(new T());
}
and class which is useful if the method mutates its parameter, which wont work for structs
static void IncA<T>(T item) where T: class, IA
{
item.A++;
}
The real power of generics is when methods have a generic return type or generic classes like List <T>. You dont want to implement a new class for every List you will need.

C# Generics: there is no way to constrain a type to have a static method?

Could somebody kindly explain this to me, in simple words:
there is no way to constrain a type to
have a static method. You cannot, for
example, specify static methods on an
interface.
many thanks in advance to you lovely people :)
With generics, you can add a constraint that means the generic-type supplied must meet a few conditions, for example:
where T : new() - T must have a public parameterless constructor (or be a struct)
where T : class - T must be a reference-type (class / interface / delegate)
where T : struct - T must be a value-type (other than Nullable<TSomethingElse>)
where T : SomeBaseType - T must be inherited from SomeBaseType (or SomeBaseType itself)
where T : ISomeInterface - T must implement ISomeInterface
for example:
public void SomeGenericMethod<T>(T data) where T : IEnumerable {
foreach(var obj in data) {
....
}
}
it is SomeBaseType and ISomeInterface that are interesting here, as they allow you to demand (and use) functions defined on those types - for example, where T : IList gives you access to Add(...) etc. HOWEVER! simply: there is no such mechanism for things like:
constructors with parameters
static methods
operators / conversions
arbitrary methods not defined via a base-type or interface
so: you can't demand those, and you can't use them (except via reflection). For some of those dynamic can be used, though.
so, basically:
public class A{}
public class B{
public static void Foo() {}
}
You can't write a generic constraint for T in:
public class C<T> {}
Such that you restrict to accept only A or B based on the presence or non-presence of the static method Foo().
Imagine the following not working code:
interface IWithStatic
{
void DoIt(); // non-static
static void DoItStatic(); // static
}
class C1 : IWithStatic
{
void DoIt() {} // non-static
static void DoItStatic(){} // static
}
class C2 : IWithStatic
{
void DoIt() {} // non-static
static void DoItStatic(){} // static
}
And, in a program :
IWithStatic myObj = GetWithAnyMethod(); // Return a C1 or C2 instance
myObj.DoIt(); // working, as the runtime type is used (either C1 or C2);
but with the static... how can the compiler interpret this :
IWithStatic.DoItStatic(); // Not knowing which type to use
Do you see what's the problem now ?
It is not possible to have:
public interface IInterface {
static void Method();
}
This is because you are not allowed/able to constrain implementing classes to methods being static.

Get derived class type from a base's class static method

i would like to get the type of the derived class from a static method of its base class.
How can this be accomplished?
Thanks!
class BaseClass {
static void Ping () {
Type t = this.GetType(); // should be DerivedClass, but it is not possible with a static method
}
}
class DerivedClass : BaseClass {}
// somewhere in the code
DerivedClass.Ping();
This can be accomplished easily using the curiously recurring template pattern
class BaseClass<T>
where T : BaseClass<T>
{
static void SomeMethod() {
var t = typeof(T); // gets type of derived class
}
}
class DerivedClass : BaseClass<DerivedClass> {}
call the method:
DerivedClass.SomeMethod();
This solution adds a small amount of boilerplate overhead because you have to template the base class with the derived class.
It's also restrictive if your inheritance tree has more than two levels. In this case, you will have to choose whether to pass through the template argument or impose the current type on its children with respect to calls to your static method.
And by templates I, of course, mean generics.
If I'm not mistaken, the code emitted for BaseClass.Ping() and DerivedClass.Ping() is the same, so making the method static without giving it any arguments won't work. Try passing the type as an argument or through a generic type parameter (on which you can enforce an inheritance constraint).
class BaseClass {
static void Ping<T>() where T : BaseClass {
Type t = typeof(T);
}
}
You would call it like this:
BaseClass.Ping<DerivedClass>();
A static method is defined on the type. There is no "this". You'll need to make this an instance method, instead:
class BaseClass {
public void Ping() {
Type t = this.GetType(); // This will work, since "this" has meaning here...
}
You can then do:
class DerivedClass : BaseClass {}
DerivedClass instance = new DerivedClass();
instance.Ping();
In short this is what I tried to answer here. It uses one interface to unify all derived classes and let them all call the same static method from the base class without passing a Type.
public interface IDerived
{
}
public class BaseClass<T> where T : IDerived
{
public static void Ping()
{
//here you have T = the derived type
}
}
public class DerivedClass : BaseClass<DerivedClass>, IDerived
{
//with : BaseClass<DerivedClass> we are defining the T above
}
public class ExampleApp
{
public void Main()
{
//here we can call the BaseClass's static method through DerivedClass
//and it will know what Type calls it
DerivedClass.Ping();
}
}
Just a guess (not tested)
Type t = MethodBase.GetCurrentMethod().DeclaringType;
It's not possible to get the derived class from a static method. As an example to illustrate why, imagine BaseClass has 2 subclasses - DerivedClass and AnotherDerivedClass - which one should be returned? Unlike polymorphic non-static methods, there is no possible association with a derived class calling a static method on a base class - the compile time type and runtime type are the same with a static method call.
You can either make the method non-static, so you then get the correct type via polymorphism, or create static method "overrides" in the subclasses, e.g.
class DerivedClass : BaseClass
{
void Ping() {
BaseClass.Ping();
// or alternatively
BaseClass.Ping(Type.GetType("DerivedClass"));
}
}
Your client code can then call the method in the derived class to explicitly indicate it want's the derived class version. If necessary, you might then also pass the DerivedClass type as a parameter to the base class method, to provide context that the method was called via the derived class.
Why not just use the methods that are there already?
If you have
class BaseClass {}
partial class DerivedClass : BaseClass {}
You can look at
DerivedClass.GetType().BaseType;
I think the following will work for this case (and several similar ones elsewhere on SO). Perf won't be too good, but if this is infrequent, that won't be a problem.
Create a stacktrace and parse it looking for a derived class. In the general case this wouldn't be too reliable or might not even work, but in specific cases, like that in the OP, I believe this will work fine. In Powershell:
$strace = (new-object diagnostics.stacktrace).tostring()
#
$frames = $strace -split " at "
$typesFromFrames = $frames | select -skip 1| # skip blank line at the beginning
% { ($_ -split "\(",2)[0]} | # Get rid of parameters string
% {$_.substring(0,$_.lastindexof("."))} | # Get rid of method name
$ {$_ -as [type]}
#
# In powershell a lot of the frames on the stack have private classes
# So $typesFromFrames.count is quite a bit smaller than $frames.count
# For the OP, I don't think this will be a problem because:
# 1. PS isn't being used
# 2. The derived class in the OP isn't private
# (if it is then tweaks will be needed)
#
$derivedOnStack = $typesFromFrames | ? { $_.issubclassof( [BaseClass])}
Hopefully there will just be one element in $derivedOnStack, but it will depend on the particulars of the application. Some experimentation will be required.

Categories

Resources