I'm trying to upgrade my general class design skills in C#, and want you guys to reveal code-smells I might have. (hope general discussions are allowed at Stackoverflow.com)
Regarding to This Tutorial, I wrapped this up to C# and tried to chain constructors, avoid same attribute signatures and solve it the right way, without duplicating code.
The problem in this tutorial: The Running Back and Wide Receiver would use the same attribute signatures. Multiple constructions for each player role would cause errors. Instead you might use object creation.
Below, how I solved it.
Football Player class:
public class FootballPlayer
{
public double PasserRating { get; set; } // Specific to QBs
public int RushingYards { get; set; } // Specific to RBs & QBs
public int ReceivingYards { get; set; } // Specific to RBs & WRs
public int TotalTackles { get; set; } // Specific to DEF
public int Interceptions { get; set; } // Specific to DEF
public int FieldGoals { get; set; } // Specific to Kickers
public double AvgPunt { get; set; } // Specific to Punters
public double AvgKickoffReturn { get; set; }// Specific to Special Teams
public double AvgPuntreturn { get; set; } // Specific to Special Teams
private FootballPlayer() : this(0.0, 0, 0, 0, 0, 0, 0.0, 0.0, 0.0) { }
private FootballPlayer(double passerRating, int rushingYards, int receivingYards, int totalTackles, int interceptions, int fieldGoals, double avgPunt, double avgKickoffReturn, double avgPuntreturn)
{
PasserRating = passerRating;
RushingYards = rushingYards;
ReceivingYards = receivingYards;
TotalTackles = totalTackles;
Interceptions = interceptions;
FieldGoals = fieldGoals;
AvgPunt = avgPunt;
AvgKickoffReturn = avgKickoffReturn;
AvgPuntreturn = avgPuntreturn;
}
public static FootballPlayer CreateQb(double passerRating, int rushingYards)
{
return new FootballPlayer
{
PasserRating = passerRating,
RushingYards = rushingYards
};
}
public static FootballPlayer CreateRb(int rushingYards)
{
return new FootballPlayer
{
RushingYards = rushingYards
};
}
public static FootballPlayer CreateWr(int receivingYards)
{
return new FootballPlayer
{
ReceivingYards = receivingYards
};
}
}
Program:
class Program
{
static void Main()
{
var aaronRodgers = FootballPlayer.CreateQb(132.0, 259);
var drewBrees = FootballPlayer.CreateQb(129.6, 244);
Console.WriteLine("Aaron Rodgers passer Rating: {0}", aaronRodgers.PasserRating);
// OUTPUT: Aaron Rodgers passer Rating: 132
Console.WriteLine("Drew Brees passer Rating: {0}", drewBrees.PasserRating);
// OUTPUT: Drew Brees passer Rating: 129.6
Console.ReadLine();
}
}
Would you guys say that's the way to go?
Or what should I take into account?
Related
I have a unit test with FluentAssertions, where I want to test an object equivalent.
[TestFixture]
public class TaskCompletionTest
{
private string _callId;
private List<Step> _steps;
private SolidColorBrush _solidColor;
[SetUp]
public void ReInitializeTest()
{
_callId = _faker.Name.FullName();
_steps = new List<Step> { new Step { Name = "Step1" }, new Step { Name = "Step2" } };
_solidColor = new SolidColorBrush(Color.FromRgb(0, 0, 0));
}
[Test]
public void ShouldCreateTaskCompletion()
{
//Arrange
var taskCompletion = new TaskCompletionwModel(_callId, _steps);
//Acts
var taskCompletionExpected = new
{
CallId = _callId,
Steps = _steps,
StatusColor = _solidColor
};
//Assert
taskCompletionExpected.Should().BeEquivalentTo(taskCompletion);
}
}
public class Step
{
public string Name { get; set; }
}
public class TaskCompletionwModel
{
public string CallId { get; private set; }
public List<Step> Steps { get; private set; }
public SolidColorBrush StatusColor { get; set; } = new SolidColorBrush(Color.FromRgb(0, 0, 0));
public TaskCompletionwModel(string callId, List<Step> steps)
{
CallId = callId;
Steps = steps;
}
}
When I run the test I have this.
Expected member StatusColor to be #FF000000, but found #FF000000.
With configuration:
- Use declared types and members
- Compare enums by value
- Match member by name (or throw)
- Without automatic conversion.
- Be strict about the order of items in byte arrays
Why this test doesn´t work?
Best regards.
Jolynice
Hello I found the problem, I need to cast the type of the SolidColorBrush.
var taskCompletionExpected = new
{
CallId = _callId,
Steps = _steps,
StatusColor = (SolidColorBrush) _solidColor,
};
Done,
Best regards.
I have a list of programmers:
programmers.Add(new Programmer("Jake", 1.9, 2000));
programmers.Add(new Programmer("Richard", 1.0, 1300));
and I need to create a new list of sorted programmers by this
value => 2000 / 1.9.(upward)
I can't figure out how to divide int by double and sort the programmers by this result. Can you please help me how to do so?
So far I've tried:
var ProgrammersSorted = programmers.OrderBy((x,y) => x.DailyWage / y.Speed).ToList();
Programmer class:
public class Programmer
{
public string Name { get; private set; }
public double Speed { get; private set; }
public int DailyWage { get; private set; }
public Project Project { get; private set; }
public string ProjectName
{
get
{
return Project?.Name ?? "No project assigned";
}
}
public Programmer(string name, double speed, int dailyWage)
{
Name = name;
Speed = speed;
DailyWage = dailyWage;
}
}
You are very close. Try this out:
var programmersSorted = programmers.OrderBy(x => x.DailyWage / x.Speed).ToList();
Please try below code, I think this will solve your issue.
var programmers = new List<Programmer>
{
new Programmer("SS",12.3,2345),
new Programmer("ADE",1.21,22345),
new Programmer("AR",12.2,23445),
new Programmer("NK",12.5,23455)
};
var progrmrs = programmers.OrderBy(t => t.DailyWage / t.Speed).ToList();
Console.WriteLine("Name\t Speed\t DailyWage");
foreach (var prgrm in progrmrs)
{
Console.WriteLine("{0}\t {1}\t {2}", prgrm.Name, prgrm.Speed, prgrm.DailyWage);
}
I have the following object:
namespace BluetoothExample
{
public class Assay
{
public double Band_1 //Vis450
{
get;
set;
}
public double Band_2 //Vis500
{
get;
set;
}
public double Band_3 //Vis550
{
get;
set;
}
public double Band_4 //Vis570
{
get;
set;
}
}
}
I want to populate the 4 bands in my object. Which I currently do in the following way:
public Populate()
{
int _i = 0;
double[] nirData = new double[4];
MyDevice.Characteristic.ValueUpdated += (sender, e) =>
{
nirData[_i] = BitConverter.ToDouble(e.Characteristic.Value, 0);
_i++;
};
Assay assay = new Assay();
assay.Band_1 = nirData[0];
assay.Band_2 = nirData[1];
assay.Band_3 = nirData[2];
assay.Band_4 = nirData[3];
}
I was wondering if it was possible to do the entire thing inside the MyDevice.Characteristic.ValueUpdate method instead? My thought is that it should be possible to increment and populate the properties of my object like so:
string name = "assay.Band_" + _i;
name = BitConverter.ToDouble(e.Characteristic.Value, 0);
This is obviously wrong, but it sort of demonstrates my idea.
Just make your band an Array, or List:
public class Assay
{
public double[] Band
{
get;
set;
}
}
And then you can simply assign it like:
public Populate()
{
int _i = 0;
double[] nirData = new double[4];
MyDevice.Characteristic.ValueUpdated += (sender, e) =>
{
nirData[_i] = BitConverter.ToDouble(e.Characteristic.Value, 0);
_i++;
};
Assay assay = new Assay();
assay.Band = nirData;
}
I have the following classes hierarchy:
abstract class Product : IComparable
{
public string Name { get; set; }
public decimal Price { get; set; }
public string Barcode { get; set; }
public int CompareTo(object obj)
{
int ret = -1;
if (String.Compare(this.GetType().Name, obj.GetType().Name,StringComparison.Ordinal) == 0)
ret = 0;
return ret;
}
}
abstract class Book : Product
{
public int PagesCount { get; set; }
}
class ProgrammingBook : Book
{
public string ProgrammingLanguage { get; set; }
}
class CulinaryBook : Book
{
public string MainIngridient { get; set; }
}
class EsotericBook : Book
{
public int MininumAge { get; set; }
}
abstract class Disc : Product
{
internal enum Content
{
Music,
Video,
Software
}
public Content DiscContent { get; set; }
}
class CdDisc : Disc
{
}
class DvdDisc : Disc
{
}
And I trying to sort following collection by using IComparable interface method CompareTo:
List<Product> products = new List<Product>
{
new DvdDisc {Name = "The lord of the rings 2",DiscContent = Disc.Content.Video,Price = 200M,Barcode = "5435443-2"},
new CdDisc {Name = "Antonio Vivaldi: best picks",Price = 700M, DiscContent = Disc.Content.Music,Barcode = "4543765-565"},
new CulinaryBook{Name = "Midterranian foods",MainIngridient = "Salmon",PagesCount = 436,Price = 350M,Barcode = "41457561-897"},
new CdDisc{Name = "Windows XP", DiscContent = Disc.Content.Software, Price = 950M, Barcode = "5433668-4"},
new EsotericBook{Name = "Russian Freemasonry 1731-2000",MininumAge = 21,PagesCount = 2100,Price = 3000M,Barcode = "6464632-876"},
new CdDisc {Name = "The best of Mussorgsky",Price = 300M, DiscContent = Disc.Content.Music,Barcode = "5435436-567"},
new ProgrammingBook{Name = "CLR via C#",PagesCount = 900, Price = 1110M,ProgrammingLanguage = "C#",Barcode = "5546533-2446"},
new DvdDisc {Name = "The lord of the rings 1",DiscContent = Disc.Content.Video,Price = 200M,Barcode = "54354423-2"},
new ProgrammingBook{Name = "ASP.NET MVC 4",PagesCount = 800,Price = 1200M,ProgrammingLanguage = "C#",Barcode = "46476573-65"},
new EsotericBook{Name = "Russian Freemasonry in it's future and past",MininumAge =19, PagesCount = 900, Price = 2342M,Barcode = "3656353-24"},
new CulinaryBook{Name = "Traditional Polish dishes",MainIngridient = "Red meat",PagesCount = 630,Price = 840,Barcode = "54634234-5"}
}; products.Sort();
Output list should look like this:
1.1 Programming books
1.2 Culinary books
1.3 Esoteric books
2.1 Cd discs sorted by content
2.2 DVD discs sorted by content
My current CompareTo method does only part of the job - comparing classes by name.
This is a working example that will render the exact same output:
1.1 Programming books
1.2 Culinary books
1.3 Esoteric books
2.1 Cd discs sorted by content
2.2 DVD discs sorted by content
I also added IComparable<Product> to more easily make it comparable with other products.
abstract class Product : IComparable<Product>
{
public string Name { get; set; }
public decimal Price { get; set; }
public string Barcode { get; set; }
protected abstract int InternalSortOrder { get; }
protected virtual string SortBy { get {return Name;} }
public int CompareTo(Product obj)
{
var sameType = string.Compare(GetType().Name, obj.GetType().Name, StringComparison.Ordinal) == 0;
var sameBaseType = GetType().BaseType != null && obj.GetType().BaseType != null &&
string.Compare(GetType().BaseType.ToString(), obj.GetType().BaseType.ToString(),
StringComparison.Ordinal) == 0;
// They have the same base type, but not the same type. Order by base type first.
if (!sameType && !sameBaseType && GetType().BaseType != null && obj.GetType().BaseType != null)
{
// Order by base type first.
return string.Compare(GetType().BaseType.ToString(), obj.GetType().BaseType.ToString(),
StringComparison.Ordinal);
}
// it's the same base type (eg. book or disc)
if (sameBaseType)
{
// Order by sort order.
if (obj.InternalSortOrder != this.InternalSortOrder)
{
return InternalSortOrder.CompareTo(obj.InternalSortOrder);
}
}
if (sameType)
{
// Same sort order. We sort by name.
return string.Compare(SortBy, obj.SortBy, StringComparison.Ordinal);
}
// Order by Type.
return string.Compare(GetType().Name, obj.GetType().Name, StringComparison.Ordinal);
}
}
abstract class Book : Product
{
public int PagesCount { get; set; }
}
class ProgrammingBook : Book
{
public string ProgrammingLanguage { get; set; }
protected override int InternalSortOrder
{
get { return 1; }
}
}
class CulinaryBook : Book
{
public string MainIngridient { get; set; }
protected override int InternalSortOrder
{
get { return 2; }
}
}
class EsotericBook : Book
{
public int MininumAge { get; set; }
protected override int InternalSortOrder
{
get { return 3; }
}
}
abstract class Disc : Product
{
internal enum Content
{
Music,
Video,
Software
}
protected override string SortBy
{
get { return DiscContent.ToString(); }
}
public Content DiscContent { get; set; }
}
class CdDisc : Disc
{
protected override int InternalSortOrder
{
get { return 1; }
}
}
class DvdDisc : Disc
{
protected override int InternalSortOrder
{
get { return 2; }
}
}
UPDATE:
I've added virtual SortByin Product. It will go to Name by default, but Disc will return Content.
You need to work with equals option
rtn = Primary Sort;
if(rtn =0)
rtn =secondary Sort;
if(rtn =0)
rtn =tertiary Sort;
as your primary sort seems to be on the type of book
you would do
rtn = this.GetType().Name.CompareTo(obj.GetType().Name);
if(rtn ==0)
rtn =this.Name.CompareTo(obj.Name);
return rtn;
if your problem is that you don't want alphabetic sorting on the type
then add to product
public abstract int SortOrder{get;}
and use that as your primary sort
I have written a web service and constructor that adds objects to my list. I am getting an error that makes no sense to me because I am passing in the 3 parameters I should be passing in.
The error is:
There is no argument given that corresponds to the required formal
parameter 'myArticleID' of
'MainPage.GetTileDetails.GetTileDetails(string, string, int)'
Here is my code:
Web Service:
[OperationContract]
List<ViewDetails> ViewDetails();
[DataContract]
public class ViewDetails
{
[DataMember]
public string TitleView { get; set; }
[DataMember]
public string BodyView { get; set; }
[DataMember]
public int ArticleID { get; set; }
public ViewDetails() { }
public ViewDetails(string myTitleView, string myBodyView, int myArticleID)
{
this.TitleView = myTitleView;
this.BodyView = myBodyView;
this.ArticleID = myArticleID;
}
}
Project where i am using web service
public async void ViewData()
{
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
List<GetTileDetails> tileList = new List<GetTileDetails>();
var res = await client.ViewDetailsAsync();
for (int i = 0; i < res.Count; i++)
{
tileList.Add(new GetTileDetails(res[i].TitleView, res[i].BodyView.Substring(0, 170) + " ..."), res[i].ArticleID);
}
tileGridView.ItemsSource = tileList;
}
public class GetTileDetails
{
public string TitleView { get; set; }
public string BodyView { get; set; }
public int ArticleID { get; set; }
public GetTileDetails() { }
public GetTileDetails(string myTitleView, string myBodyView, int myArticleID)
{
this.TitleView = myTitleView;
this.BodyView = myBodyView;
this.ArticleID = myArticleID;
}
}
Can anyone tell me why I am getting that error? I am passing in (string, string, int)....
Replace this line:
tileList.Add(new GetTileDetails(res[i].TitleView, res[i].BodyView.Substring(0, 170) + " ..."), res[i].ArticleID);
with this one:
tileList.Add(new GetTileDetails(res[i].TitleView, res[i].BodyView.Substring(0, 170) + " ...", res[i].ArticleID));
Note you have a misplaced ) right after " ...").