I'm trying to create a class called User that can register new Users and store them in a list. Currently, I just want to be able to use the RegisterUser object. I have a C# book and have tried understanding it, but it's not clicking. Any help or hints in the right direction are very much appreciated.
namespace UserClass {
/// <summary>
/// The user class
/// <summary>
public class User {
public string userName;
public string password;
public string address;
public int contactNumber;
public static RegisterUser(string username, string pass, string add, int contact) {
User newUser = new User();
newUser.userName = username;
newUser.password = pass;
newUser.address = add;
newUser.contactNumber = contact;
WriteLine(newUser);
};
}
}
CodePudding user response:
A few issues with your code:
WriteLine
is incorrect unless you've created that method
I think you're looking for Console.WriteLine(...)
which you can
use after adding using System;
however even that would be
incorrect.
I assume you are looking to print the values of fields in
the User
class which in that case, either override .ToString
(bad idea) or access and print them separately.
RegisterUser
has no return type
It could be void
-> public static void RegisterUser(string username, string pass, string add, int contact)
indicating that nothing is returned.
However, common convention and expectation would be that the new User
object is returned so that the caller can know what the final state of the operation was ->
- You have a rogue
;
at the end of the implementation ofRegisterUser(...)
You need to remove it to make your code compile.
- You actually have no variables anywhere, which would allow you to create a collection
You need to add your users to something like a List<User>
, which would be encapsulated internally in another class perhaps called UserManager
. This allows you to expose behaviour but hide the implementation, as well as adhering to SRP.
You could then expose the collection of users if you needed to, in a clear way, using a ReadOnlyCollection<User>
.
This would show consumers that they would probably have to call a method (RegisterUser
) to be able to add to the collection of users as ReadOnlyCollection<User>
prevents modification, and not just do users.Add(...)
& bypass your registration logic.
In this case, RegisterUser
would also not have the static
keyword, as it would need access to the instance field - your collection of users - and it won't be able to do that as a static method.
- Your namespace is extremely specific to your
User
class
It's technically okay but namespaces are used to organise classes & control scope. I would rename it to something more related to your domain, as opposed to something bound to your class name (UserClass
).
- Arguments for
RegisterUser
I would also cut down on the number of arguments to RegisterUser
, take in a User
object and then enforce all fields being set using the constructor for User
.
This would turn it into a monadic method, making the code more readable, easier to test later on and makes you keep a conscious tab on how many "things" the method is responsible for.
Something like the below should work:
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace MyApplication
{
public class User
{
public string UserName;
public string Password;
public string Address;
public int ContactNumber;
public User(string username, string pass, string add, int contact)
{
UserName = username;
Password = pass;
Address = add;
ContactNumber = contact;
}
}
public class UserManager
{
private readonly List<User> _users = new List<User>();
public ReadOnlyCollection<User> GetUsers()
{
return _users.AsReadOnly();
}
public User RegisterUser(User newUser)
{
// process user, modify fields, add etc.
_users.Add(newUser);
return newUser;
}
}
public static class UserOutput
{
public static void WriteUserToConsole(User user)
{
Console.WriteLine($"{user.UserName}, {user.Password}, {user.Address}, {user.ContactNumber}");
}
}
}
var userManager = new UserManager();
var userToBeRegistered = new User("A", "B", "C", 0);
var createdUser = userManager.RegisterUser(userToBeRegistered);
UserOutput.WriteUserToConsole(createdUser);
var allUsers = userManager.GetUsers();
foreach (var user in allUsers)
UserOutput.WriteUserToConsole(user);
CodePudding user response:
you are nearly there
public class User
{
public string userName;
public string password;
public string address;
public int contactNumber;
}
// Separate Class to create and store the users
public class UserController
{
// List to store your Users
public List<User> UserList;
// Constuctor instatiates UserList
public UserController()
{
UserList = new List<User>();
}
public void RegisterUser(string username, string pass, string add, int contact) {
User newUser = new User();
newUser.userName = username;
newUser.password = pass;
newUser.address = add;
newUser.contactNumber = contact;
// Adding the user to the UserList
UserList.Add(newUser);
// Show the userName of the new User in Console
Console.WriteLine(newUser.userName);
}
}
you can now Register users with your method in the new separate class. They will be stored in the UserList that you can access freely from outside of the class.
usage:
//get a UserController to start working
UserController controller = new UserController();
// call to RegisterUser
controller.RegisterUser("bob", "1234", "mystreet 1", 42);
CodePudding user response:
I feel like you are close. See if the following points will help.
RegisterUser
is a function/method with no purpose as it is missing a return type specification. Here you have two design options:Create a new user and return a variable referencing this user.
static User RegisterUser( ... ) { newUser = new User(); ... return newUser; }
Create a new user and store the user internally to a list. This means the function specification must have
void
in its return type.static List<User> userList = new List<User>(); static void RegisterUser( ... ) { newUser = new User(); ... userList.Add(newUser); }
You can specify the required information to define a user by declaring a constructor which assigns this information when a new User object is created. For example, if the
username
andpassword
are the only required field thenCreate a constructor accepting these two values
public class User { ... public User(string userName, string password) { this.userName = userName; this.password = password; } }
Change the fields on readonly such that they cannot be modified at a later time.
public class User { public readonly string userName; public readonly string password; public string address; public int contactNumber; ... }
There is no defined way to display the information for each user on the console and so a call to
Console.WriteLine(user)
will only display the user type (default behavior of C#). To add this functionality to a class, override theToString()
method.public class User { ... public override string ToString() { return $"User = {userName}, Address = {address}, Contact = {contactNumber}"; } }
Now in the main program when you loop through the registered users, you can simply invoke
Console.WriteLine()
on each one to show on the screen the information.static void Main(string[] args) { User.RegisterUser("aaa", "abc1", "100 east", 55500); User.RegisterUser("xyz", "uvw5", "120 north", 55501); foreach (var user in User.registededUsers) { Console.WriteLine(user); } }
it is common practice to hide fields behind properties. In this case it would be useful not to expose the list of registered users outside of the class as
List<User>
because it will allow the addition of new items in the list without requiring to call theRegisterUser()
function. To disallow this behavior remove thepublic
from theregistededUsers
field and add a property calledRegisteredUsers
expose this field as aIReadOnlyList<User>
public class User { ... static List<User> registededUsers = new List<User>(); public static IReadOnlyList<User> RegisteredUsers { get => registededUsers.AsReadOnly(); } }