Daryl Gill
Daryl Gill

Reputation: 5524

Use linq to return a selection of data from list<t>

I have the following code:

public class UserList
    {
        public string UName { get; set; }
        public string Auth { get; set; }
        public Boolean PUser { get; set; }
    }


    class DeveloperPreview
    {
        List<UserList> UserList = new List<UserList>();
        public void PopulateUsers()
        {
            UserList.Add(new UserList() { UName="Daryl",Auth="12345",PUser=true});
            UserList.Add(new UserList() { UName = "Test", Auth = "239", PUser = false });
            UserList.Add(new UserList() { UName="Developer",Auth="2",PUser=true});

        }

        public string Authenticateuser(string Username, string Auth)
        {
            var User = UserList.Where((t => t.UName.Contains(Username)));
            return User.UName;
        }

    }

which is being invoked by:

    DeveloperPreview Dev = new DeveloperPreview();
    private void SubmitClick(object sender, RoutedEventArgs e)
    {
        Dev.PopulateUsers();
        string Auth = Dev.Authenticateuser("Daryl","2");
        MessageBox.Show(Auth);
    }

I'm having trouble returning only the rows in the list which contains "Daryl"

I have used this as a reference: C# LINQ select from list

But am still having some-what difficulty on how to actually perform this task, I later wish to manipulate/work with the data gathered from the list, but that's another bridge that will be built when necessary

Upvotes: 0

Views: 401

Answers (5)

David
David

Reputation: 10708

What's happening here is that .Where is narrowing down the list, but will always return an IEnumerable<>, even if that enumerable only contains one element. If you want to return a single row, you need to add a call to one of the following methods

  • .First() returns the first element, Errors if there is no first element
  • .FirstOrDefault() returns the first element, or null if there are none
  • .Single() Returns the single object, or errors if there isn't exactly one object
  • .SingleOrDefault() Returns the single object, null if there is none, and errors if there is more than one

Note that all but these extension methods return IEnumerable so that you can chain calls to them, such as

UserList
    .Where( t => t.UName.Contains(Username) )
    .Select( t => t.UName )
    .DefaultIfEmpty(string.Empty)
    .First();

Upvotes: 1

Habib
Habib

Reputation: 223422

The problem is in following lines:

 var User = UserList.Where((t => t.UName.Contains(Username)));
 return User.UName;

Enumerable.Where will return an IEnumerable<T>, which is a collection of records not a single record. So later when you try to access User.UName then you will get an error. You need to select a single record. You can use First / FirstOrDefault / Single / SingleOrDefault based on your requirement. Your method could be:

public string Authenticateuser(string Username, string Auth)
{
    var User = UserList.FirstOrDefault(t => t.UName.Contains(Username));
    if(User != null)    
       return User.UName;
    else  //user not found
       return null;//throw exception / Message etc
}

Read about: LINQ Single vs SingleOrDefault vs First vs FirstOrDefault

Upvotes: 4

Kritner
Kritner

Reputation: 13765

You could use:

var User = UserList.Where(t => t.UName == Username).FirstOrDefault();

I don't know if it will cause issues, but having property names matching object names could get quite confusing. You're using "UserList" to represent a List of UserList objects.

I would think this would make more sense:

public class User
{
    public string UName { get; set; }
    public string Auth { get; set; }
    public Boolean PUser { get; set; }
}

class DeveloperPreview
{
    List<User> UserList = new List<User>();
    public void PopulateUsers()
    {
        UserList.Add(new User() { UName="Daryl",Auth="12345",PUser=true});
        UserList.Add(new User() { UName = "Test", Auth = "239", PUser = false });
        UserList.Add(new User() { UName="Developer",Auth="2",PUser=true});

    }

    public string Authenticateuser(string Username, string Auth)
    {
        var user = UserList.Where(t => t.UName == Username).FirstOrDefault();
        return user.UName;
    }

}

Upvotes: 1

Matt Burland
Matt Burland

Reputation: 45155

This:

var User = UserList.Where((t => t.UName.Contains(Username)));

Returns an IEnumerable<T>, not a single item. What you probably want is:

var User = UserList.Where((t => t.UName.Contains(Username))).FirstOrDefault();

This will return the first matching item (or null if none is found).

Upvotes: 1

Zach Spencer
Zach Spencer

Reputation: 1889

I think all you really need to do is change this:

var User = UserList.Where((t => t.UName.Contains(Username)));

to this:

var User = UserList.Where((t => t.UName.Contains(Username))).FirstOrDefault();

The Where statement returns an IEnumerable, you need the first result from that IEnumerable.

Upvotes: 1

Related Questions