House plan design (Head First C#)
$begingroup$
I've been working through the book Head First C# and this is an exercise from chapter 7, which is about interfaces and abstract classes.
I'd like a review on any and all aspects. My code ended up quite a bit different than the book's solution, because it's a few years old and I think "holds back" on newer C#/.NET features and syntax.
In a shared code base, I would include that XML documentation, but since this is just local code for learning, I didn't. Any and all feedback appreciated.
The authors' published implementation is here on GitHub. The idea is to implement a floor plan that can be explored, with room connections and doors to the outside. It's done through a WinForms application.
Here is a picture of the plan from the book. Sorry, couldn't find a screenshot.
The app looks like this:
Location.cs
using System;
namespace House
{
abstract class Location
{
public Location(string name) => Name = name;
public string Name { get; private set; }
public Location Exits;
public virtual string Description
{
get
{
string description = $"You're standing in the {Name}. You see exits to the following places: rn";
foreach (Location exit in Exits)
{
description += $"— {exit.Name}";
if (exit != Exits[Exits.Length - 1])
{
description += "rn";
}
}
return description;
}
}
}
}
Room.cs
using System;
namespace House
{
class Room : Location
{
public Room(string name, string decoration)
: base(name)
{
Decoration = decoration;
}
private string Decoration { get; set; }
public override string Description => $"You see {Decoration}. {base.Description} ";
}
}
Outside.cs
using System;
namespace House
{
class Outside : Location
{
public Outside(string name, bool hot)
: base(name)
{
Hot = hot;
}
private bool Hot { get; }
override public string Description => Hot
? "It's very hot here. " + base.Description
: base.Description;
}
}
IHasInteriorDoor.cs
using System;
namespace House
{
interface IHasExteriorDoor
{
string DoorDescription { get; }
Location DoorLocation { get; }
}
}
OutsideWithDoor.cs
using System;
namespace House
{
class OutsideWithDoor : Outside, IHasExteriorDoor
{
public OutsideWithDoor(string name, bool hot, string doorDescription)
: base(name, hot)
{
DoorDescription = doorDescription;
}
public string DoorDescription { get; private set; }
public Location DoorLocation { get; set; }
public override string Description => $"{base.Description}rn You see {DoorDescription} to go inside.";
}
}
RoomWithDoor.cs
using System;
namespace House
{
class RoomWithDoor : Room, IHasExteriorDoor
{
public RoomWithDoor(string name, string decoration, string doorDescription)
: base(name, decoration)
{
DoorDescription = doorDescription;
}
public string DoorDescription { get; private set; }
public Location DoorLocation { get; set; }
}
}
And here is the WinForms to make it work. Leaving out IDE generated code.
ExploreTheHouseForm.cs
using System;
using System.Windows.Forms;
namespace House
{
public partial class ExploreTheHouseForm : Form
{
Location currentLocation;
RoomWithDoor livingRoom;
RoomWithDoor kitchen;
Room diningRoom;
OutsideWithDoor frontYard;
OutsideWithDoor backYard;
Outside garden;
public ExploreTheHouseForm()
{
InitializeComponent();
CreateObjects();
MoveToLocation(livingRoom);
}
private void CreateObjects()
{
// Configure the locations
livingRoom = new RoomWithDoor("living room", "an antique carpet", "an oak door with a brass knob");
kitchen = new RoomWithDoor("kitchen", "stainless steel appliances", "a screen door");
diningRoom = new Room("dining room", "a crystal chandelier");
frontYard = new OutsideWithDoor("front yard", false, livingRoom.DoorDescription);
backYard = new OutsideWithDoor("back yard", true, kitchen.DoorDescription);
garden = new Outside("garden", false);
// Configure the exits
livingRoom.Exits = new Location { diningRoom };
kitchen.Exits = new Location { diningRoom };
diningRoom.Exits = new Location { livingRoom, kitchen };
frontYard.Exits = new Location { backYard, garden };
backYard.Exits = new Location { frontYard, garden };
garden.Exits = new Location { frontYard, backYard };
// Configure exterior doors
livingRoom.DoorLocation = frontYard;
frontYard.DoorLocation = livingRoom;
kitchen.DoorLocation = backYard;
backYard.DoorLocation = kitchen;
}
private void MoveToLocation(Location location)
{
currentLocation = location;
ExitsComboBox.Items.Clear();
foreach (Location exit in location.Exits)
{
ExitsComboBox.Items.Add(exit.Name);
}
ExitsComboBox.SelectedIndex = 0;
DescriptionTextBox.Text = currentLocation.Description;
ShowGoThroughExteriorDoorButton(currentLocation);
}
private void ShowGoThroughExteriorDoorButton(Location location)
{
if (location is IHasExteriorDoor)
{
GoThroughExteriorDoorButton.Visible = true;
return;
}
GoThroughExteriorDoorButton.Visible = false;
}
private void GoHereButton_Click(object sender, EventArgs e)
{
MoveToLocation(currentLocation.Exits[ExitsComboBox.SelectedIndex]);
}
private void GoThroughExteriorDoorButton_Click(object sender, EventArgs e)
{
IHasExteriorDoor locationWithExteriorDoor = currentLocation as IHasExteriorDoor;
MoveToLocation(locationWithExteriorDoor.DoorLocation);
}
}
}
c# beginner winforms interface xaml
$endgroup$
add a comment |
$begingroup$
I've been working through the book Head First C# and this is an exercise from chapter 7, which is about interfaces and abstract classes.
I'd like a review on any and all aspects. My code ended up quite a bit different than the book's solution, because it's a few years old and I think "holds back" on newer C#/.NET features and syntax.
In a shared code base, I would include that XML documentation, but since this is just local code for learning, I didn't. Any and all feedback appreciated.
The authors' published implementation is here on GitHub. The idea is to implement a floor plan that can be explored, with room connections and doors to the outside. It's done through a WinForms application.
Here is a picture of the plan from the book. Sorry, couldn't find a screenshot.
The app looks like this:
Location.cs
using System;
namespace House
{
abstract class Location
{
public Location(string name) => Name = name;
public string Name { get; private set; }
public Location Exits;
public virtual string Description
{
get
{
string description = $"You're standing in the {Name}. You see exits to the following places: rn";
foreach (Location exit in Exits)
{
description += $"— {exit.Name}";
if (exit != Exits[Exits.Length - 1])
{
description += "rn";
}
}
return description;
}
}
}
}
Room.cs
using System;
namespace House
{
class Room : Location
{
public Room(string name, string decoration)
: base(name)
{
Decoration = decoration;
}
private string Decoration { get; set; }
public override string Description => $"You see {Decoration}. {base.Description} ";
}
}
Outside.cs
using System;
namespace House
{
class Outside : Location
{
public Outside(string name, bool hot)
: base(name)
{
Hot = hot;
}
private bool Hot { get; }
override public string Description => Hot
? "It's very hot here. " + base.Description
: base.Description;
}
}
IHasInteriorDoor.cs
using System;
namespace House
{
interface IHasExteriorDoor
{
string DoorDescription { get; }
Location DoorLocation { get; }
}
}
OutsideWithDoor.cs
using System;
namespace House
{
class OutsideWithDoor : Outside, IHasExteriorDoor
{
public OutsideWithDoor(string name, bool hot, string doorDescription)
: base(name, hot)
{
DoorDescription = doorDescription;
}
public string DoorDescription { get; private set; }
public Location DoorLocation { get; set; }
public override string Description => $"{base.Description}rn You see {DoorDescription} to go inside.";
}
}
RoomWithDoor.cs
using System;
namespace House
{
class RoomWithDoor : Room, IHasExteriorDoor
{
public RoomWithDoor(string name, string decoration, string doorDescription)
: base(name, decoration)
{
DoorDescription = doorDescription;
}
public string DoorDescription { get; private set; }
public Location DoorLocation { get; set; }
}
}
And here is the WinForms to make it work. Leaving out IDE generated code.
ExploreTheHouseForm.cs
using System;
using System.Windows.Forms;
namespace House
{
public partial class ExploreTheHouseForm : Form
{
Location currentLocation;
RoomWithDoor livingRoom;
RoomWithDoor kitchen;
Room diningRoom;
OutsideWithDoor frontYard;
OutsideWithDoor backYard;
Outside garden;
public ExploreTheHouseForm()
{
InitializeComponent();
CreateObjects();
MoveToLocation(livingRoom);
}
private void CreateObjects()
{
// Configure the locations
livingRoom = new RoomWithDoor("living room", "an antique carpet", "an oak door with a brass knob");
kitchen = new RoomWithDoor("kitchen", "stainless steel appliances", "a screen door");
diningRoom = new Room("dining room", "a crystal chandelier");
frontYard = new OutsideWithDoor("front yard", false, livingRoom.DoorDescription);
backYard = new OutsideWithDoor("back yard", true, kitchen.DoorDescription);
garden = new Outside("garden", false);
// Configure the exits
livingRoom.Exits = new Location { diningRoom };
kitchen.Exits = new Location { diningRoom };
diningRoom.Exits = new Location { livingRoom, kitchen };
frontYard.Exits = new Location { backYard, garden };
backYard.Exits = new Location { frontYard, garden };
garden.Exits = new Location { frontYard, backYard };
// Configure exterior doors
livingRoom.DoorLocation = frontYard;
frontYard.DoorLocation = livingRoom;
kitchen.DoorLocation = backYard;
backYard.DoorLocation = kitchen;
}
private void MoveToLocation(Location location)
{
currentLocation = location;
ExitsComboBox.Items.Clear();
foreach (Location exit in location.Exits)
{
ExitsComboBox.Items.Add(exit.Name);
}
ExitsComboBox.SelectedIndex = 0;
DescriptionTextBox.Text = currentLocation.Description;
ShowGoThroughExteriorDoorButton(currentLocation);
}
private void ShowGoThroughExteriorDoorButton(Location location)
{
if (location is IHasExteriorDoor)
{
GoThroughExteriorDoorButton.Visible = true;
return;
}
GoThroughExteriorDoorButton.Visible = false;
}
private void GoHereButton_Click(object sender, EventArgs e)
{
MoveToLocation(currentLocation.Exits[ExitsComboBox.SelectedIndex]);
}
private void GoThroughExteriorDoorButton_Click(object sender, EventArgs e)
{
IHasExteriorDoor locationWithExteriorDoor = currentLocation as IHasExteriorDoor;
MoveToLocation(locationWithExteriorDoor.DoorLocation);
}
}
}
c# beginner winforms interface xaml
$endgroup$
add a comment |
$begingroup$
I've been working through the book Head First C# and this is an exercise from chapter 7, which is about interfaces and abstract classes.
I'd like a review on any and all aspects. My code ended up quite a bit different than the book's solution, because it's a few years old and I think "holds back" on newer C#/.NET features and syntax.
In a shared code base, I would include that XML documentation, but since this is just local code for learning, I didn't. Any and all feedback appreciated.
The authors' published implementation is here on GitHub. The idea is to implement a floor plan that can be explored, with room connections and doors to the outside. It's done through a WinForms application.
Here is a picture of the plan from the book. Sorry, couldn't find a screenshot.
The app looks like this:
Location.cs
using System;
namespace House
{
abstract class Location
{
public Location(string name) => Name = name;
public string Name { get; private set; }
public Location Exits;
public virtual string Description
{
get
{
string description = $"You're standing in the {Name}. You see exits to the following places: rn";
foreach (Location exit in Exits)
{
description += $"— {exit.Name}";
if (exit != Exits[Exits.Length - 1])
{
description += "rn";
}
}
return description;
}
}
}
}
Room.cs
using System;
namespace House
{
class Room : Location
{
public Room(string name, string decoration)
: base(name)
{
Decoration = decoration;
}
private string Decoration { get; set; }
public override string Description => $"You see {Decoration}. {base.Description} ";
}
}
Outside.cs
using System;
namespace House
{
class Outside : Location
{
public Outside(string name, bool hot)
: base(name)
{
Hot = hot;
}
private bool Hot { get; }
override public string Description => Hot
? "It's very hot here. " + base.Description
: base.Description;
}
}
IHasInteriorDoor.cs
using System;
namespace House
{
interface IHasExteriorDoor
{
string DoorDescription { get; }
Location DoorLocation { get; }
}
}
OutsideWithDoor.cs
using System;
namespace House
{
class OutsideWithDoor : Outside, IHasExteriorDoor
{
public OutsideWithDoor(string name, bool hot, string doorDescription)
: base(name, hot)
{
DoorDescription = doorDescription;
}
public string DoorDescription { get; private set; }
public Location DoorLocation { get; set; }
public override string Description => $"{base.Description}rn You see {DoorDescription} to go inside.";
}
}
RoomWithDoor.cs
using System;
namespace House
{
class RoomWithDoor : Room, IHasExteriorDoor
{
public RoomWithDoor(string name, string decoration, string doorDescription)
: base(name, decoration)
{
DoorDescription = doorDescription;
}
public string DoorDescription { get; private set; }
public Location DoorLocation { get; set; }
}
}
And here is the WinForms to make it work. Leaving out IDE generated code.
ExploreTheHouseForm.cs
using System;
using System.Windows.Forms;
namespace House
{
public partial class ExploreTheHouseForm : Form
{
Location currentLocation;
RoomWithDoor livingRoom;
RoomWithDoor kitchen;
Room diningRoom;
OutsideWithDoor frontYard;
OutsideWithDoor backYard;
Outside garden;
public ExploreTheHouseForm()
{
InitializeComponent();
CreateObjects();
MoveToLocation(livingRoom);
}
private void CreateObjects()
{
// Configure the locations
livingRoom = new RoomWithDoor("living room", "an antique carpet", "an oak door with a brass knob");
kitchen = new RoomWithDoor("kitchen", "stainless steel appliances", "a screen door");
diningRoom = new Room("dining room", "a crystal chandelier");
frontYard = new OutsideWithDoor("front yard", false, livingRoom.DoorDescription);
backYard = new OutsideWithDoor("back yard", true, kitchen.DoorDescription);
garden = new Outside("garden", false);
// Configure the exits
livingRoom.Exits = new Location { diningRoom };
kitchen.Exits = new Location { diningRoom };
diningRoom.Exits = new Location { livingRoom, kitchen };
frontYard.Exits = new Location { backYard, garden };
backYard.Exits = new Location { frontYard, garden };
garden.Exits = new Location { frontYard, backYard };
// Configure exterior doors
livingRoom.DoorLocation = frontYard;
frontYard.DoorLocation = livingRoom;
kitchen.DoorLocation = backYard;
backYard.DoorLocation = kitchen;
}
private void MoveToLocation(Location location)
{
currentLocation = location;
ExitsComboBox.Items.Clear();
foreach (Location exit in location.Exits)
{
ExitsComboBox.Items.Add(exit.Name);
}
ExitsComboBox.SelectedIndex = 0;
DescriptionTextBox.Text = currentLocation.Description;
ShowGoThroughExteriorDoorButton(currentLocation);
}
private void ShowGoThroughExteriorDoorButton(Location location)
{
if (location is IHasExteriorDoor)
{
GoThroughExteriorDoorButton.Visible = true;
return;
}
GoThroughExteriorDoorButton.Visible = false;
}
private void GoHereButton_Click(object sender, EventArgs e)
{
MoveToLocation(currentLocation.Exits[ExitsComboBox.SelectedIndex]);
}
private void GoThroughExteriorDoorButton_Click(object sender, EventArgs e)
{
IHasExteriorDoor locationWithExteriorDoor = currentLocation as IHasExteriorDoor;
MoveToLocation(locationWithExteriorDoor.DoorLocation);
}
}
}
c# beginner winforms interface xaml
$endgroup$
I've been working through the book Head First C# and this is an exercise from chapter 7, which is about interfaces and abstract classes.
I'd like a review on any and all aspects. My code ended up quite a bit different than the book's solution, because it's a few years old and I think "holds back" on newer C#/.NET features and syntax.
In a shared code base, I would include that XML documentation, but since this is just local code for learning, I didn't. Any and all feedback appreciated.
The authors' published implementation is here on GitHub. The idea is to implement a floor plan that can be explored, with room connections and doors to the outside. It's done through a WinForms application.
Here is a picture of the plan from the book. Sorry, couldn't find a screenshot.
The app looks like this:
Location.cs
using System;
namespace House
{
abstract class Location
{
public Location(string name) => Name = name;
public string Name { get; private set; }
public Location Exits;
public virtual string Description
{
get
{
string description = $"You're standing in the {Name}. You see exits to the following places: rn";
foreach (Location exit in Exits)
{
description += $"— {exit.Name}";
if (exit != Exits[Exits.Length - 1])
{
description += "rn";
}
}
return description;
}
}
}
}
Room.cs
using System;
namespace House
{
class Room : Location
{
public Room(string name, string decoration)
: base(name)
{
Decoration = decoration;
}
private string Decoration { get; set; }
public override string Description => $"You see {Decoration}. {base.Description} ";
}
}
Outside.cs
using System;
namespace House
{
class Outside : Location
{
public Outside(string name, bool hot)
: base(name)
{
Hot = hot;
}
private bool Hot { get; }
override public string Description => Hot
? "It's very hot here. " + base.Description
: base.Description;
}
}
IHasInteriorDoor.cs
using System;
namespace House
{
interface IHasExteriorDoor
{
string DoorDescription { get; }
Location DoorLocation { get; }
}
}
OutsideWithDoor.cs
using System;
namespace House
{
class OutsideWithDoor : Outside, IHasExteriorDoor
{
public OutsideWithDoor(string name, bool hot, string doorDescription)
: base(name, hot)
{
DoorDescription = doorDescription;
}
public string DoorDescription { get; private set; }
public Location DoorLocation { get; set; }
public override string Description => $"{base.Description}rn You see {DoorDescription} to go inside.";
}
}
RoomWithDoor.cs
using System;
namespace House
{
class RoomWithDoor : Room, IHasExteriorDoor
{
public RoomWithDoor(string name, string decoration, string doorDescription)
: base(name, decoration)
{
DoorDescription = doorDescription;
}
public string DoorDescription { get; private set; }
public Location DoorLocation { get; set; }
}
}
And here is the WinForms to make it work. Leaving out IDE generated code.
ExploreTheHouseForm.cs
using System;
using System.Windows.Forms;
namespace House
{
public partial class ExploreTheHouseForm : Form
{
Location currentLocation;
RoomWithDoor livingRoom;
RoomWithDoor kitchen;
Room diningRoom;
OutsideWithDoor frontYard;
OutsideWithDoor backYard;
Outside garden;
public ExploreTheHouseForm()
{
InitializeComponent();
CreateObjects();
MoveToLocation(livingRoom);
}
private void CreateObjects()
{
// Configure the locations
livingRoom = new RoomWithDoor("living room", "an antique carpet", "an oak door with a brass knob");
kitchen = new RoomWithDoor("kitchen", "stainless steel appliances", "a screen door");
diningRoom = new Room("dining room", "a crystal chandelier");
frontYard = new OutsideWithDoor("front yard", false, livingRoom.DoorDescription);
backYard = new OutsideWithDoor("back yard", true, kitchen.DoorDescription);
garden = new Outside("garden", false);
// Configure the exits
livingRoom.Exits = new Location { diningRoom };
kitchen.Exits = new Location { diningRoom };
diningRoom.Exits = new Location { livingRoom, kitchen };
frontYard.Exits = new Location { backYard, garden };
backYard.Exits = new Location { frontYard, garden };
garden.Exits = new Location { frontYard, backYard };
// Configure exterior doors
livingRoom.DoorLocation = frontYard;
frontYard.DoorLocation = livingRoom;
kitchen.DoorLocation = backYard;
backYard.DoorLocation = kitchen;
}
private void MoveToLocation(Location location)
{
currentLocation = location;
ExitsComboBox.Items.Clear();
foreach (Location exit in location.Exits)
{
ExitsComboBox.Items.Add(exit.Name);
}
ExitsComboBox.SelectedIndex = 0;
DescriptionTextBox.Text = currentLocation.Description;
ShowGoThroughExteriorDoorButton(currentLocation);
}
private void ShowGoThroughExteriorDoorButton(Location location)
{
if (location is IHasExteriorDoor)
{
GoThroughExteriorDoorButton.Visible = true;
return;
}
GoThroughExteriorDoorButton.Visible = false;
}
private void GoHereButton_Click(object sender, EventArgs e)
{
MoveToLocation(currentLocation.Exits[ExitsComboBox.SelectedIndex]);
}
private void GoThroughExteriorDoorButton_Click(object sender, EventArgs e)
{
IHasExteriorDoor locationWithExteriorDoor = currentLocation as IHasExteriorDoor;
MoveToLocation(locationWithExteriorDoor.DoorLocation);
}
}
}
c# beginner winforms interface xaml
c# beginner winforms interface xaml
edited 2 mins ago
Phrancis
asked 9 mins ago
PhrancisPhrancis
14.7k646139
14.7k646139
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211662%2fhouse-plan-design-head-first-c%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211662%2fhouse-plan-design-head-first-c%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown