C # class return type

If I have an abstract class, is it possible to somehow return an enumerator of the type of the derived class? Or will I have to use generics in a base class or a generic method? Here's a really dumb example of what I'm trying to do -

public abstract class Person { public IEnumerable<MyType> Search() { DbDataReader reader = Database.Instance.ExecuteReader(sql); while(reader.Read()) { MyType row = new MyType(); row.Load(reader); yeild return row; } } private Load(DbDataReader reader) { //load instance from reader row } //declare properties that can be searched, such as Location } public class Programmer : Person { //declare properties that can be searched, such as Language } 

Then in another place I would like to call

 Programmer programmer = new Programmer(); programmer.Location = "My city"; programmer.Language = "C#"; foreach(Programmer programmer in programmer.Search()) { //display list of c# programmers in my city } 

I know that I can do this using a general method, for example, Search<T>() , but I would like to be able to call the search function from a class that does not know exactly what the Person type is (for example, the base class for the AJAX handler)

If this is not possible, can someone give me an example or reason why not? Or will it be too difficult to implement in the compiler?

+4
source share
5 answers

If you are looking for an approach with this “nice” use, I suggest ExtensionMethod. With Ext, you do not have to define an effective object type twice. programmer.Search<Programmer>() => programmer.Search()

 public static PersonExtensions { public static IEnumerable<TType> Search<TType>(this TType row) : where TType : new(), Person { DbDataReader reader = Database.Instance.ExecuteReader(sql); while(reader.Read()) { var row = new TType() row.Load(reader); yeild return row; } } } 
+1
source

There is no reason why you cannot use your search method:

 public IEnumerable<T> Search<T>() where T : MyType, new() { DbDataReader reader = Database.Instance.ExecuteReader(sql); while(reader.Read()) { T row = new T(); row.Load(reader); yield return row; } } 

and call programmer.Search<Programmer>() .

Where MyType come from btw? Should there be a Person ?

+3
source

See http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx

The covariance on the types of returned virtual methods is a fairly frequently requested function, and I will use it if I had one. He never made a panel because (1) the CLR does not support it; we need to either generate a lot of helper code behind the scenes to make it work, or convince the CLR command to change (the C ++ / CLI team did the first) (2), in most cases you can generate the necessary helper functions yourself quite easily; just create a “new” method that has the correct return type that delegates its implementation to the virtual method, and (3) Anders does not consider it a particularly important function. - Eric

So no, that’s impossible, and YES, that’s because it’s too complicated.

+3
source

@ben dotnet: the fact that there is no need to pass an efficient type is clearly not related to the fact that it is an extension method. This is due to the mecanism of output and will also occur on any kind of method (extension or regular).

In this method, the prototype

 public static IEnumerable<TType> Search<TType>(this TType row) : where TType : new(), Person 

TType knows that the compiler is the same as 4 times per line. Thus, when calling a method, it is enough to know the type of programmer to know that it will be the same type between <...> . That is why we can omit it. It also works if there is no parameter prefixed with the this .

+1
source

You can use a generic type in a base class and define your generic type in a derived class as a derived class.

 public abstract class Person<T> where T : Person<T> { public IEnumerable<T> Search() { DbDataReader reader = Database.Instance.ExecuteReader(sql); while (reader.Read()) { var row = new T(); row.Load(reader); yield return row; } } protected virtual void Load(DbDataReader reader){} } public class Programmer : Person<Programmer>{} 
0
source

All Articles