2017-04-02 1 views
-5

Je suis tombé sur la publication sur stackoverflow qui fournissait une solution à la question en enchaînant deux méthodes. La réponse ressemblait à ceci:La méthode C# ne renvoie pas d'objet - chaînage de méthodes

public x DoThis() 
{ 
    //do something 
    return this; 

} 

public x DoThat() 
{ 
    //do something else 
    return this; 

} 

var x = new x().DoThis().DoThat; 

Je lis des méthodes de chaînage. Mais quelque chose ne semble pas être juste dans ce cas. J'ai créé une classe appelée Library avec deux méthodes différentes qui retournent le même type, et je peux accéder à la première des méthodes, mais pas à la seconde. À moins que je fasse quelque chose de mal, cette solution est incorrecte.

J'ai regardé un tutoriel sur la création de méthodes d'extension de collection et je voulais essayer d'utiliser cette approche. Je dois admettre que je ne comprends pas encore tout à ce sujet. Donc, je pensais, je devrais pouvoir utiliser IEnumerable <> parce que je suis la seule collection de passer à cette classe

Voici une classe:

class Library 
{ 
    private IEnumerable<Movie> MoviesLibrary; 


    public Library(IEnumerable<Movie> library) 
    { 
     this.MoviesLibrary = library.ToList(); 

    } 

    public IEnumerable<Movie> FindMovie(int _movieId) 
    { 


     return this.MoviesLibrary.Where(movie => movie.MovieId == _movieId); 


    } 

    public IEnumerable<Movie> GetByYear(int _year) 
    { 

     return this.MoviesLibrary.Where(movie => movie.Year == _year); 

    } 

} 

Comme je comprends la déclaration « retourner ce » devrait revenir en objet instancié. Dans la méthode chaînée, la méthode suivante doit utiliser cet objet retourné et effectuer sa propre action.

+2

Comprenez-vous ce que ['this'] (https://msdn.microsoft.com/fr-fr/library/dk1507sz.a spx) est? –

+0

Question est très confuse, mais il semble que vous voulez "méthode chaining" - http://stackoverflow.com/questions/1119799/method-chaining-in-c-sharp –

+0

J'ai édité mon message initial – tipitoe

Répondre

0

Pouvez-vous fournir plus de contexte pour le premier exemple de code que vous avez donné? (celui qui ne fonctionne pas - par exemple qu'est-ce que X dans votre cas? Quelle classe a la première méthode?).

Le dernier exemple vous a donné

public IEnumerable<Movie> GetByYear(int _year) 
{ 
    this.MoviesLibrary.Where(movie => movie.MovieId == _movieId); 
    return this; 
} 

est incorrect parce que vous retourner un IEnumerable, et IEnumerable n'a pas la méthode supplémentaire qui ne sont pas des méthodes d'extension.

Les méthodes d'extension peuvent en effet vous aider à réaliser ce que vous voulez. En fait, Linq est mis en œuvre comme un ensemble de méthodes d'extension pour IEnumerable

Voir https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,577032c8811e20d3

pour plus d'informations (et des exemples comment écrire des méthodes d'extension).

Aussi, vous pouvez en savoir plus sur la méthode d'extension dans leur page msdn formelle https://msdn.microsoft.com/en-us/library/bb383977.aspx

+0

J'ai édité mon article initial – tipitoe

+0

Je pense que vous avez manqué quelques connaissances (ça va) - Je peux vous donner des réponses courtes mais pour comprendre la base de la langue, vous devrez vous plonger dans de la documentation (C# en un mot est le meilleur livre que j'ai lu pour C#) ... pas de soucis à ce sujet :) ... mais à partir de votre post édité, je pense qu'il peut être préférable de lire sur les principes fondamentaux de la langue d'abord .... Actuellement, l'exemple 'Library' même compiler - afin de compiler il doit implémenter IEnumerable ... le chaînage que vous voulez ne fonctionnera que si le type de retour des méthodes est aussi Bibliothèque et Bibliothèque est IEnumerable. – sokohavi

+0

J'ai édité la dernière méthode et les deux retournent le même type IEnumerable tipitoe

0

Ceci est une solution à ma propre question. Je dois admettre qu'il n'est pas clair dès le début ce que j'essayais d'accomplir, ce qui est évident dans le montage du message initial. Le premier exemple de code est une réponse à une question similaire postée par quelqu'un d'autre sur ce site. Il est très général dans la nature, cependant vous pouvez voir clairement que cette personne essaie de défendre qu'il est possible d'enchaîner les méthodes en retournant le même type d'objet. Je voulais accomplir quelque chose de similaire après avoir regardé le tutoriel intitulé «Rendre votre code C# plus orienté objet» de Zoran Horvat. Ce tutoriel est disponible sur Pluralsight. Son exemple utilise des interfaces et des méthodes d'extension dans les chapitres 4 et 5. L'idée de cette solution est quelque peu similaire, mais je voulais que cette fonctionnalité soit contenue dans une seule classe.

Je pense que toute la confusion est liée au type de l'objet que la méthode doit retourner afin de fournir une fonctionnalité de chaînage. Jetons un coup d'oeil à un exemple de chaîne simple

someString.ToUpper.ToLower.Trim

La première chose qui vient à l'esprit est que la chaîne est passée d'une méthode à une autre méthode et à chaque étape, elle est modifiée par cette méthode. Par conséquent, nous aurions une situation similaire lorsque vous travaillez avec des collections.

movies.GetByYear (1999) .GetByGroup (1) .GetByGenre ("Action")

Dans ce cas, nous commençons par une liste qui est passé à travers cette chaîne de méthodes. Il est également très probable que nous pensons que toutes les méthodes de cette chaîne fonctionnent sur la même liste. Après tout, la propriété de chaîne de l'exemple précédent est partagée par toutes les méthodes même si elle est en cours de modification. Ce n'est pas ce qui se passe réellement avec cette collection de films. Chaque méthode fonctionne avec une collection de taille différente. Il semble que GetByYear() et GetByGroup() sont des méthodes qui fonctionnent avec la même liste de films, ce sont en fait des objets Library séparés qui ont des listes complètement différentes.

Je voudrais remercier Sokohavi qui a laissé des commentaires sur le retour de l'objet Library. Il suggère également de créer l'objet Bibliothèque IEnumerable. Malheureusement, si vous pensez que cette méthode devrait retourner IEnumerable, alors vous êtes sur le mauvais chemin. Techniquement parlant, Library est une liste, mais la liste qui contient les objets Movie est définie sur private et n'est pas visible pour les autres objets. Par conséquent, il n'y a rien à parcourir. L'objet Bibliothèque n'a que des méthodes de couplage, et si vous en sélectionnez un, vous perdrez l'accès aux autres méthodes de la même classe. Par conséquent, la méthode doit renvoyer l'objet Library afin d'accéder à toutes les méthodes de la même classe, et la liste qui stocke l'objet Movie doit être IEnumerable. Il y a un inconvénient à cette approche. Vous ne pouvez pas charger de données dans cette liste à l'intérieur du constructeur de la bibliothèque. Au lieu de cela, les données sont passées en paramètre. Maintenant, vous avez des objets qui ont différentes listes de films et la façon dont ils communiquent entre eux est à travers leurs constructeurs. Ci-dessous nous avons la classe Repository qui charge des éléments individuels dans une liste à travers son constructeur. La classe Library définit des méthodes qui fourniront un filtrage de la liste qui lui est transmise. Vous pouvez également créer une autre couche d'abstraction qui utiliserait cette fonctionnalité.

public class Movie 
{ 
    public string Title { get; set; } 
    public int Year { get; set; } 
    public int GroupId { get; set; } 
    public string Genre { get; set; } 

} 

public class Repository 
{ 

    private List<Movie> localDb; 

    public Repository() 
    { 
     localDb = new List<Movie>(); 


    } 


    public IEnumerable<Movie> GetAllMovies() 
    { 
     localDb = new List<Movie>(); 

     var movie1 = new Movie() { Title = "Movie1", Year = 2000, GroupId = 1, Genre = "Action" }; 
     var movie2 = new Movie() { Title = "Movie2", Year = 1999, GroupId = 1, Genre = "Drama" }; 
     var movie3 = new Movie() { Title = "Movie3", Year = 2000, GroupId = 1, Genre = "Comedy" }; 
     var movie4 = new Movie() { Title = "Movie4", Year = 2000, GroupId = 2, Genre = "Action" }; 
     var movie5 = new Movie() { Title = "Movie5", Year = 1999, GroupId = 2, Genre = "Drama" }; 
     var movie6 = new Movie() { Title = "Movie6", Year = 1999, GroupId = 2, Genre = "Drama" }; 
     var movie7 = new Movie() { Title = "Movie7", Year = 1999, GroupId = 2, Genre = "Horror" }; 


     localDb.Add(movie1); 
     localDb.Add(movie2); 
     localDb.Add(movie3); 
     localDb.Add(movie4); 
     localDb.Add(movie5); 
     localDb.Add(movie6); 
     localDb.Add(movie7); 


     return localDb; 
    } 
} 

public class Library 
{ 
    private IEnumerable<Movie> MoviesLibrary; 

    public Library(IEnumerable<Movie> movies) 
    { 

     this.MoviesLibrary = movies.ToList(); 

    } 

    public Library GetByYear(int year) 
    { 
     return new Library(this.MoviesLibrary.Where(movie => movie.Year == year)); 


    } 

    public Library GetById(int id) 
    { 
     return new Library(this.MoviesLibrary.Where(movie => movie.GroupId == id)); 


    } 


    public IEnumerable<Movie> GetByGenre(string genre) 
    { 
     return this.MoviesLibrary.Where(movie => movie.Genre == genre); 

    } 


    public void Display()   
    { 

     foreach (var movie in this.MoviesLibrary) 
     { 
      Console.WriteLine("Title: {0} , Year {1}, Group: {2}, Genre: {3}", movie.Title,movie.Year,movie.GroupId, movie.Genre); 
     } 



    } 

} 

Comment utiliser ces classes:

 var repository = new Repository(); 
     var listOfMovies = repository.GetAllMovies(); 
     var movies = new Library(listOfMovies); 

     var selectedMovies1 = movies.GetByYear(2000).GetById(1).GetByGenre("Action"); 
     var selectedMovies2 = movies.GetByYear(2000).GetById(2); 


     foreach (var movie in selectedMovies1) 
     { 
      Console.WriteLine("Selected 1 - Title: {0} , Year {1}, Group: {2}, Genre: {3}", movie.Title,movie.Year,movie.GroupId, movie.Genre); 



     } 

     selectedMovies2.Display(); 

Sortie:

choisi 1 - Titre: Film1, Année 2000, Groupe: 1, Genre: Action

Titre: MOVIE4 , Année 2000, Groupe: 2, Genre: Action