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.
Note that the class design was mandated by the authors, I'm open to suggestions to improve.
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# 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.
Note that the class design was mandated by the authors, I'm open to suggestions to improve.
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# 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.
Note that the class design was mandated by the authors, I'm open to suggestions to improve.
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# 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.
Note that the class design was mandated by the authors, I'm open to suggestions to improve.
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# winforms interface xaml
c# winforms interface xaml
edited 3 hours ago
Phrancis
asked 4 hours ago
PhrancisPhrancis
14.7k646139
14.7k646139
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
$begingroup$
I have a general rule: if I see string concatenation with a loop I assume it's not the best way of doing it. Let's look at this:
foreach (Location exit in Exits)
{
description += $"— {exit.Name}";
if (exit != Exits[Exits.Length - 1])
{
description += "rn";
}
}
I see this pattern a lot. What you need is Select
with string.Join
:
var exitList = string.Join(Environment.NewLine, Exits.Select(exit => $"— {exit.Name}"));
I've used Environment.NewLine
because I like using well-named constants. Random aside: r
is a Carriage Return and n
is a Line Feed. The terminology comes from physical printers. Another reason I prefer Environment.NewLine
is that it means you don't have to know and remember that.
The Name
property of Location
is only set in the constructor. You can use a read-only auto property instead of a private set one:
public string Name { get; }
Outside.Description
could be using string interpolation like the other Description properties.
You're missing your access modifiers on your class declarations. MS guidelines state that they should always be specified.
I'm not aware of a convention for it but override public string
seems to be an odd order to me. I would expect the access modifier first: public override string
. The main thing is to keep that consistent though.
$endgroup$
add a comment |
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');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
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
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
I have a general rule: if I see string concatenation with a loop I assume it's not the best way of doing it. Let's look at this:
foreach (Location exit in Exits)
{
description += $"— {exit.Name}";
if (exit != Exits[Exits.Length - 1])
{
description += "rn";
}
}
I see this pattern a lot. What you need is Select
with string.Join
:
var exitList = string.Join(Environment.NewLine, Exits.Select(exit => $"— {exit.Name}"));
I've used Environment.NewLine
because I like using well-named constants. Random aside: r
is a Carriage Return and n
is a Line Feed. The terminology comes from physical printers. Another reason I prefer Environment.NewLine
is that it means you don't have to know and remember that.
The Name
property of Location
is only set in the constructor. You can use a read-only auto property instead of a private set one:
public string Name { get; }
Outside.Description
could be using string interpolation like the other Description properties.
You're missing your access modifiers on your class declarations. MS guidelines state that they should always be specified.
I'm not aware of a convention for it but override public string
seems to be an odd order to me. I would expect the access modifier first: public override string
. The main thing is to keep that consistent though.
$endgroup$
add a comment |
$begingroup$
I have a general rule: if I see string concatenation with a loop I assume it's not the best way of doing it. Let's look at this:
foreach (Location exit in Exits)
{
description += $"— {exit.Name}";
if (exit != Exits[Exits.Length - 1])
{
description += "rn";
}
}
I see this pattern a lot. What you need is Select
with string.Join
:
var exitList = string.Join(Environment.NewLine, Exits.Select(exit => $"— {exit.Name}"));
I've used Environment.NewLine
because I like using well-named constants. Random aside: r
is a Carriage Return and n
is a Line Feed. The terminology comes from physical printers. Another reason I prefer Environment.NewLine
is that it means you don't have to know and remember that.
The Name
property of Location
is only set in the constructor. You can use a read-only auto property instead of a private set one:
public string Name { get; }
Outside.Description
could be using string interpolation like the other Description properties.
You're missing your access modifiers on your class declarations. MS guidelines state that they should always be specified.
I'm not aware of a convention for it but override public string
seems to be an odd order to me. I would expect the access modifier first: public override string
. The main thing is to keep that consistent though.
$endgroup$
add a comment |
$begingroup$
I have a general rule: if I see string concatenation with a loop I assume it's not the best way of doing it. Let's look at this:
foreach (Location exit in Exits)
{
description += $"— {exit.Name}";
if (exit != Exits[Exits.Length - 1])
{
description += "rn";
}
}
I see this pattern a lot. What you need is Select
with string.Join
:
var exitList = string.Join(Environment.NewLine, Exits.Select(exit => $"— {exit.Name}"));
I've used Environment.NewLine
because I like using well-named constants. Random aside: r
is a Carriage Return and n
is a Line Feed. The terminology comes from physical printers. Another reason I prefer Environment.NewLine
is that it means you don't have to know and remember that.
The Name
property of Location
is only set in the constructor. You can use a read-only auto property instead of a private set one:
public string Name { get; }
Outside.Description
could be using string interpolation like the other Description properties.
You're missing your access modifiers on your class declarations. MS guidelines state that they should always be specified.
I'm not aware of a convention for it but override public string
seems to be an odd order to me. I would expect the access modifier first: public override string
. The main thing is to keep that consistent though.
$endgroup$
I have a general rule: if I see string concatenation with a loop I assume it's not the best way of doing it. Let's look at this:
foreach (Location exit in Exits)
{
description += $"— {exit.Name}";
if (exit != Exits[Exits.Length - 1])
{
description += "rn";
}
}
I see this pattern a lot. What you need is Select
with string.Join
:
var exitList = string.Join(Environment.NewLine, Exits.Select(exit => $"— {exit.Name}"));
I've used Environment.NewLine
because I like using well-named constants. Random aside: r
is a Carriage Return and n
is a Line Feed. The terminology comes from physical printers. Another reason I prefer Environment.NewLine
is that it means you don't have to know and remember that.
The Name
property of Location
is only set in the constructor. You can use a read-only auto property instead of a private set one:
public string Name { get; }
Outside.Description
could be using string interpolation like the other Description properties.
You're missing your access modifiers on your class declarations. MS guidelines state that they should always be specified.
I'm not aware of a convention for it but override public string
seems to be an odd order to me. I would expect the access modifier first: public override string
. The main thing is to keep that consistent though.
answered 48 mins ago
RobHRobH
14.4k42661
14.4k42661
add a comment |
add a comment |
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');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
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');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
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');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
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');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
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