Good afternoon, very much I float in a subject about the generalized interfaces, methods. I would be very grateful for the hint, or for the links in which direction to dig, read. I read the theory from the website professorweb.ru about interfaces, generalization. The theory by the theory that I understood something, which is not, but in practice I still cannot implement the next task.

For example, there is a code:

DataPerson dataPerson; IEnumerable<Person> person = dataPerson.<IEnumerable<Person>>Get(); // как я понял, метод Get() должен в person записать значение ссылочного типа // на реализующий интерфейс типа Person? Не представляю как реализовать это. // В плане непонятны мне следующие вопросы: // 1. Где следует реализовать этот интерфейс? // 2. Не понимаю про двойное обобщение вида <T<V>>, // а именно каким образом это указать в методе Get()? // 3. Не понимаю как вернуть интерфейс через метод. 

Person class:

 class Person { public string FirstName { get; set; } public string LastName { get; set; } public Person(string fName, string lName) { FirstName = fName; LastName = lName; } } 

DataPerson class:

 class DataPerson { // как я примерно представляю объявление функции Get() public IEnumerable Get<T,V>() where T : IEnumerable<V> { // как реализовать, к сожалению не представляю } } 

How to actually implement the Get () method in the DataPerson class?

  • The implementation will obviously depend on what exactly you are getting the data from. Where does DataPerson have to get the list? from the base? from a text file? pull off webservice. (although personally it seems to me that this is some kind of overddesign for the sake of overdesign). how should he create new objects without knowing anything about their particular type? - PashaPash
  • In a real task, the System.Linq library is used, and the DataContext class is used, and an instance is declared of the form DataContext dataContext = new StorageDataContext (); where StorageDataContext is a class that must implement the Get () method; - ixe
  • So add this to the question. it is not yet clear what the difficulty is with you - actually, returning an IEnumerable, knowing how to create objects? if yes, then it is easy enough to do :) - PashaPash
  • but to fully bind it to the database is a question of the level “how do I write my ORM”. and the answer to it is quite extensive. maybe you should look in the direction of EF? - PashaPash
  • @PashaPash, "what exactly is the problem with you - actually, returning an IEnumerable, knowing how to create objects?" Yes, there is a difficulty, can you please in more detail? - ixe

2 answers 2

Your method is likely to be declared as

 class DataPerson { public IEnumerable<T> Get<T>() where T : new() { } } 

because in reality, he has only one type-parameter — the type of objects to be selected.

and used as

 IEnumerable<Person> person = dataPerson<Person>Get(); 

You can implement it in two ways:

Really create something that implements an IEnumerable interface. For example, an array or list. Fill it and return from the method:

 class DataPerson { public IEnumerable<T> Get<T>() where T : new() { var query = buildSomeQueryFor(typeof(T)); // построить запрос для выбора объектов типа T DataRow[] dataRows = selectSomeRowsFromDB(query); // var result = new List<T>(); foreach (var row in dataRows) { result.Add(MapDataRowTo<T>(row)); } return result; } private MapDataRowTo<T>(DataRow row) where T : new () { var newObject = new T(); // map values from row to newObject // return return newObject; } } 

The second way is to use the yield keyword:

 class DataPerson { public IEnumerable<T> Get<T>() where T : new() { var query = buildSomeQueryFor(typeof(T)); // построить запрос для выбора объектов типа T DataRow[] dataRows = selectSomeRowsFromDB(query); // foreach (var row in dataRows) { yield return MapDataRowTo<T>(row); } } private MapDataRowTo<T>(DataRow row) where T : new () { var newObject = new T(); // map values from row to newObject // return return newObject; } } 

Using yield will wrap your meta in an IEnumerable wrapper, which will return items as they are called from the calling code. Those. execution of the Get<T> method will occur in chunks, from one call to yield to the next. In MSDN there is enough detailed documentation on this feature of language .

  • Thank you very much, with your help I am not swimming so much in this topic .. - ixe
  • @PashaPash, please tell me, what's the point of such a definition class DataPerson { public IEnumerable<T> Get<T>() where T : new() { } } ? In theory, the class name implies that the DataPerson.Get method creates objects of type Person. Those. Get <T> () should be replaced by Get () and removed where T: new (). Or I'm wrong? - Stack
  • @Stack honestly - I do not know. this is not my definition :). Topicaster wanted a version with generics - I left the generics, making it as simple as possible. in general, yes, generics are not needed there. - PashaPash
  • @Stack my answer is more about yield than about generics - PashaPash
  • @PashaPash if "generics are not needed there", then probably it is better to change the answer in part "the method most likely should be declared as ...". - Stack

How to actually implement the Get () method in the DataPerson class?

 class DataPerson { public IEnumerable<Person> Get() { return new List<Person>() { new Person(), new Person() }; } // или так public IEnumerable<Person> Get() { return new[] { new Person(), new Person() }; } } 
  • Thank you very much for the answer, and with your help I also made some changes and now the situation has become more transparent. :) - ixe