How to use Property inside Method in C# - c#

How to use Property inside method in right way. I was searching on the internet but I can't found property is used inside method that will be returned value.
public class OET
{
public int ShiftTime { get; set; }
public int BreakTime { get; set; }
public int DownTime { get; set; }
public int ProductionTarget { get; set; }
public int IdealRunRate { get; set; }
public int PrductionOneShift { get; set; }
public int RejectedProduct { get; set; }
public int planedProductionTime(int shift, int breaktime) {
shift = ShiftTime;
breaktime = BreakTime;
return shift - breaktime;
}
I would like to use property to get value from "PlanedProductionTIme" method, is it code above right?

Your example isn't very clear, because you're passing in two parameters, but then ignoring them in your calculation. But if your intention was to have a property returning the calculated PlannedProductionTime, it can go like this:
public int PlannedProductionTime
{
get { return ShiftTime - BreakTime; }
}
Note that this is instead of the method - a property is a syntactic way to have a method accessed like a property:
OET myOet = new OET();
int plannedProductionTime = myOet.PlannedProductionTime;

there is no use of "sift" and "breaktime" local variable into is function. just use return ShiftTime-BreakTime.
public int method2() {
///here you are getting the peroperties value and doing calculations returns result.
return ShiftTime -BreakTime;
}
if your requirement is to set the properties value.
public void method1(int shift, int breaktime) {
ShiftTime= shift ;
BreakTime = breaktime;
}

public int PlanedProductionTime { get { return ShiftTime - BreakTime; } }
You can define the property as a calculated ones, by defining the get method in it.
More solutions - you can define a separate function and call it inside get. It will help if you want to do some more complex calculations which needs to be used somewhere else in the class - private or outside class - public.
public int PlanedProductionTime { get { return _calculatePlannedProductionTime( ShiftTime, BreakTime); } }
private\public int _calculatePlannedProductionTime (int shift, int break)
{
return shift - break;
}

Related

Initializing property value in one class using the return value of a method in a different class

I have the following structure:
public class LogicStatement : ILogicStatement
{
public string TestLogic { get; set; }
public string CompareLogic { get; set; }
public string Operator { get; set; }
public string Expression();
public bool Value();
}
public class Test : ITest
{
public int TestId { get; set; }
public int LiteralId { get; set; }
public string TestName { get; set; }
public string TestText { get; set; }
public string TestDisplayName { get; }
**public ILogicStatement LogicStatement { get; set; }**
public string Expression { get; set; }
public bool Value { get; set; }
}
public class Literal : ILiteral
{
some property members...
**public List<ITest> Tests {get; set;}**
some method members...
}
Note that the class Test has a member of type LogicStatement, and the class Literal has a member of type List.
Note also that all classes have properties and methods that share the same name: Expression, Value, Expression(), Value().
The value of Expression and Value (properties and methods) depend on values in the LogicStatement class.
Throughout the whole project, I use the Interface Type for to instantiate each object to adhere with Dependency Inversion. To support this, I use a factory-like design to create new instances of Test and LogicStatement.
Example:
public static class Factory
{
public static ILogicStatement CreateLogicStatement()
{
return new LogicStatement();
}
public static ITest CreateTest()
{
return new Test(CreateLogicStatement());
}
public static List<ITest> CreateTests()
{
return new List<ITest>();
}
//repeat the same for evey other class.
}
My goal is to have Expression() and Value() be calculated only once in the bottom level class (LogicStatement), and somehow get transfered to their counterpart properties in the higher level classes.
I'm getting the data from Dapper and it looks like all the nested objects are returned from the Dapper module correctly with the same nested structure I intended, and with the right values for all of their members. All of them but Expression, Expression(), Value, Value() are null.
my constructors look like this:
public LogicStatement()
{
Expression();
Value();
}
public Test(ILogicStatement logicStatement)
{
_logicStatement = logicStatement;
Expression = _logicStatement.Expression();
Value = _logicStatement.Value();
}
public Literal(ITest test)
{
_test = test;
Expression = _test.Expression;
Value = _test.Value;
}
and my main:
List<ILiteral> literals = Factory.CreateLiterals();
List<ITest> tests = Facotry.CreateTests();
List<ILogicStatement> logicStatements = Factory.CreateLogicStatements();
literals = GetDataFromDapper();
This last line seems to assign correct values to all other members on all hierarchies. But I cannot get Expression and Value to be anything other than null.
If I test LogicStatement.Expression() and LogicStatement.Value() standalone, they do return the expexted values. but starting at the first parent class Test, these properties are all null.
I think I'm doing something wrong in the way i'm instantiating my objects. Primarily because I'm not sure i understand basic best practices to write constructors.
Maybe I the desired behavior should be implemented through events, where the Test and Literal classes subscribe to changes in the Expression() and Value() methods (or rather to what calculates them). But I never used events and I'd like to know if this fundamentally can be acheived without them first.
My question: How do I make the Expression() Value() at the bottom level class "Fire up" whenever LogicStatement is instantiated, and then have the Expression and Value properties be assigned accordingly as a result.
In other words, I want the following to always be true:
test[i].Expression == literal[i].Expression == LogicStatement[i].Expression()
I'm a beginner in OOP. So any fundamental explanation is welcome.
As you are new to object oriented programming I would start with the basics and leave factories and adhering with Dependency Inversion and the interfaces away for later.
You could tell Dapper to split joined tables into multiple entities (see https://www.learndapper.com/relationships), but for learning OOP I would start doing everything manually.
Your class design does not look proper to me yet. Not sure what Expression and Value of the LogicStatement are, but if they are calculations based on the other properties, I would implement them as (just to show off with complicated words) lazy initialized cached getter properties that are invalidated in the setters of the relevant properties. That ensures you only calculate them once for as many reads you like but recalculate them on first read after one or multiple properties have been updated.
public class LogicStatement {
private string _testLogic;
private string _compareLogic;
private string _operator;
private string? _expression;
private bool? _value;
public LogicStatement(string testLogic, string compareLogic, string #operator) {
_testLogic = testLogic;
_compareLogic = compareLogic;
_operator = #operator;
}
public string TestLogic {
get {
return _testLogic;
}
set {
_testLogic = value;
InvalidateCachedValues();
}
}
public string CompareLogic {
get {
return _compareLogic;
}
set {
_compareLogic = value;
InvalidateCachedValues();
}
}
public string Operator {
get {
return _operator;
}
set {
_operator = value;
InvalidateCachedValues();
}
}
public string Expression {
get {
string? result = _expression;
if (result is null) {
_expression = result = BuildExpression();
}
return result;
}
}
public bool Value {
get {
bool? result = _value;
if (result is null) {
_value = result = EvaluateValue();
}
return result.Value;
}
}
private void InvalidateCachedValues() {
_expression = null;
_value = null;
}
private string BuildExpression() {
//Your logic goes here
throw new NotImplementedException();
}
private bool EvaluateValue() {
//Your logic goes here
throw new NotImplementedException();
}
}
Sorry, it got a bit bigger with the full properties.
In the other classes I would not copy the Value and the Expression but simply remove these properties as anybody can easily access them through the LogicStatement property:
public class Test {
public Test(int testId, int literalId, string testName, string testText, string testDisplayName, LogicStatement logicStatement) {
TestId = testId;
LiteralId = literalId;
TestText = testText;
TestDisplayName = testDisplayName;
LogicStatement = logicStatement;
}
public int TestId { get; }
public int LiteralId { get; }
public string TestName { get; }
public string TestText { get; }
public string TestDisplayName { get; }
public LogicStatement LogicStatement { get; }
}
and the Literal could look like this (I got a bit confused whether this class has one Test or a list of them, I stick to your constructor + properties that hint in the direction of a single one):
public class Literal {
private Test _test;
public Literal(string property1, int property2, Test test) {
Property1 = property1;
Property2 = property2;
_test = test;
}
public string Property1 { get; }
public int Property2 { get; }
public string Expression => _test.LogicStatement.Expression;
public bool Value => _test.LogicStatement.Value;
}
As you decided not to expose the Test in the Literal it makes sense to provide Expression and Value, otherwise they could also be removed (or kept for convenience).

Trying to set up Nested Object in C#, with computed field based on list

I am experimenting with a nested object class for an upcoming software project, in C#. I know how to do computed fields/properties within a class, at least as far as setting it programmatically with something like the date.
This is a little different. I am setting up a nested class like this:
string Test { get; set; }
List<Line> Detail { get; set; }
decimal Total {
get {
return TotalOf();
}
}
decimal TotalOf() {
var listQuery = this.Detail;
// This is where I'm trying to figure out how to do.
// I want the TotalOf function to return the sum of the
// Cost fields of the contained list items (Line is defined below).
// I will remove the "return 0;" eventually once
// I can figure out how to do the calculation.
return 0;
}
public class Line {
int indexOf { get; set; }
decimal Cost { get; set; }
}
That way, the field Total is automatically calculated rather than me having to compute it through the code consuming this class.
I have tried searching all over but I can't seem to find the right answer. I have plenty of time to do this, and worst case, I can just do it in the program consuming this class, but I thought I'd ask. When I hit the . after typing in this.Detail, the only aggregate function that comes up is Count.
I have tried to use the Detail.Sum function, hoping the Linq would bring up a lambda expression that I could then say "add up the Cost" but it won't come up.
I know this should be simple but I can't figure it out.
First, set access modifiers for Line properties like as public or other. Because, on default state it is private.
public class Line
{
public int indexOf { get; set; }
public decimal Cost { get; set; }
}
Then, set up root class like as LineCollection.
public class LineCollection
{
public class Line
{
public int indexOf { get; set; }
public decimal Cost { get; set; }
}
public string Test { get; set; }
public List<Line> Detail { get; set; }
public decimal Total { get; set; }
}
On LineCollection initialize default values for properties on constructor:
public class LineCollection
{
public class Line
{
public int indexOf { get; set; }
public decimal Cost { get; set; }
}
public string Test { get; set; }
public List<Line> Detail { get; set; }
public decimal Total { get; set; }
public LineCollection()
{
this.Test = string.Empty;
this.Detail = new List<Line>();
}
}
After this modify get/set accessors for Total property. I guess, property is read only and we not need to define set accessor.
public decimal Total
{
get
{
return this.Detail.Sum(x => x.Cost);
}
}
Code in get accessor automatically runs when we trying to get his value. Finally, we can run tests for checks.
LineCollection collection = new LineCollection();
collection.Detail.Add(new LineCollection.Line() { indexOf = 0, Cost = 43.3m });
collection.Detail.Add(new LineCollection.Line() { indexOf = 1, Cost = 23 });
collection.Detail.Add(new LineCollection.Line() { indexOf = 3, Cost = 56.21m });
Console.WriteLine(collection.Total.ToString());
It returns 122,51.
Think this method would work for you:
decimal TotalOf() {
return this.Detail.Select(line => line.Cost).Sum();
}
I believe this way also works:
decimal TotalOf() {
return this.Detail.Sum(line => line.Cost);
}
Hope this helps :)

OOP C# Instance field not saving data

I have a set of instance fields inherited from class G481Vars by object G481Var.
G481Vars G481Var = new G481Vars();
The values of the instance fields are assigned to through this function
private void AssignValuesG481()
{
HtmlInputText[] G481Inputs = new HtmlInputText[13] //Create an explicit array of type HtmlInputText to handle elements of input boxes on G481 tab.
{
G481Disp_Txt, G481IniVel_Txt, G481FinVel_Txt, G481Acc_Txt,
G481Time_Txt, G481Force_Txt, G481Mass_Txt, G481Weight_Txt,
G481Press_Txt, G481Dens_Txt, G481Energy_Txt, G481Area_Txt,
G481Vol_Txt
};
double[] G481List = new double[13] //Create an explicit array of type double that stores the instance fields of class G481Vars
{
G481Var.Disp, G481Var.IniVel, G481Var.FinVel, G481Var.Acc,
G481Var.Time, G481Var.Force, G481Var.Mass, G481Var.Weight,
G481Var.Press, G481Var.Dens, G481Var.Energy, G481Var.Area,
G481Var.Vol
};
for (int i = 0; i <= 12; i++) //Perform the iterative loop
{
if (G481Inputs[i].Value != "")
{
double.TryParse(G481Inputs[i].Value, out G481List[i]);
}
}
}
Where G481Vars is Defined as:
public class G481Vars
{
public double Disp { get; set; }
public double IniVel { get; set; }
public double FinVel { get; set; }
public double Acc { get; set; }
public double Time { get; set; }
public double Force { get; set; }
public double Mass { get; set; }
public double Weight { get; set; }
public double Press { get; set; }
public double Dens { get; set; }
public double Energy { get; set; }
public double Area { get; set; }
public double Vol { get; set; }
}
However when i try and access these instance fields from another function CalculateG481_Click They always return 0, even though they are assigned to before hand.
protected void CalculateG481_Click(object sender, EventArgs e)
{
AssignValuesG481();
TempInputDebugField.Value = Convert.ToString(G481Var.Disp); //This always returns 0 in the field, even though <>0 was put into the disp input field and assignvariables run.
}
When I put the TempInputDebugField code into the AssignValuesG481 function it returns the correct value. Any ideas on what is going on with the instance field?
Thanks for your help.
It seems like you think that setting the value of an element of G481List will forward that value on to the corresponding property of G481Var that was used to initialize the array. That is not true. all it does is change the values within the array.
You'll need to set the values of the instance explicitly. You could use reflection to set the properties dynamically, but with only 13 properties it would be much safer and cleaner to just set them explicitly:
G481Var.Disp = double.Parse(G481Inputs[0].Value)
G481Var.IniVel = double.Parse(G481Inputs[1].Value)
G481Var.FinVel = double.Parse(G481Inputs[2].Value)
G481Var.Acc = double.Parse(G481Inputs[3].Value)
G481Var.Time = double.Parse(G481Inputs[4].Value)
G481Var.Force = double.Parse(G481Inputs[5].Value)
G481Var.Mass = double.Parse(G481Inputs[7].Value)
G481Var.Weight = double.Parse(G481Inputs[8].Value)
G481Var.Press = double.Parse(G481Inputs[9].Value)
G481Var.Dens = double.Parse(G481Inputs[10].Value)
G481Var.Energy = double.Parse(G481Inputs[11].Value)
G481Var.Area = double.Parse(G481Inputs[12].Value)
G481Var.Vol = double.Parse(G481Inputs[13].Value)
From there you can use TryParse to better handle bad values, you can try using reflection to reduce duplicate code (at the expense of compile-time safety), etc. The point is to get something that works, then find ways to make it better. You can always go back to less "elegant" code if you get tired or stuck trying to refactor it.
Try this :
for (int i = 0; i <= 12; i++) //Perform the iterative loop
{
double val;
if (G481Inputs[i].Value != "")
{
double.TryParse(G481Inputs[i].Value, out val);
G481List[i] = val;
}
}
double is a valuetype, so when you parse the strings the values are stored only in the array. You will have to assign this values to G481Var properties:
double value;
if (double.TryParse(G481Disp_Txt.Value, out value)
G481Var.Disp = value;
Do this for each property and should works fine

Converting from on type of list to another type

I have two classes - Record and RecordModified
public class Record
{
public int RecordID { get; set; }
public int FacilityID { get; set; }
public int NewAID { get; set; }
public string OldID { get; set; }
public string Data { get; set; }
public int SyncStatusID { get; set; }
public int RecordTypeID { get; set; }//RecordTypeID is integer here.
}
The second class
public class RecordModified
{
public int RecordID { get; set; }
public int FacilityID { get; set; }
public int NewAID { get; set; }
public string OldID { get; set; }
public string Data { get; set; }
public int SyncStatusID { get; set; }
public string RecordTypeText { get; set; }//RecordTypeText is string here.
}
I have a list of Record with at least 100 Record objects, now I have to convert the List<Record> into List<RecordModified>. The RecordTypeID property of the Record class has to be converted to the property RecordTypeText of RecordModified using enums which are in a different class.
Code snippet on how I'm trying to convert:
foreach(Record r in List<Record>)
{
switch(r.RecordTypeID)
{
case (int)MyEnum.One:
listofRecordModified.Add(new RecordModified{RecordTypeID=r.RecordTypeID,...,**RecordTypeText=(MyEnum.One).ToString()})** // Notice this
break;
...........//75 more cases.
}
This solution works fine, but the problem is lot of codes and I don't think its efficient. There must be some better way to do that. Please suggest.
I think you can use ConvertAll Method along with this
List<Record> t = new List<Record>();
var result = t.ConvertAll(x => new RecordModified()
{
RecordTypeText = ((MyEnum)x.RecordTypeID).ToString()
});
If your sole problem is the conversion of the index of an enum to its text, you could use GetNames and use the index of the to get the name of the enum value used.
string text = Enum.GetNames(typeof(MyEnum))[r.RecordTypeID];
This way, you don't need the switch statement, and you can revert to one line only.
You can just use the You can do using the (MyEnum)x.RecordTypeID to cast the integer value to matching enum value. and then use that .ToString() to get string value.Linq Lambda expressions as below,
var result = RecordList.Select(x=>new RecordModified{
RecordTypeID=x.RecordTypeID,
...,
RecordTypeText=((MyEnum)x.RecordTypeID).ToString()
});
You can also use the ConvertAll as,
var result = RecordList.ConvertAll(x => new RecordModified()
{
RecordTypeText = ((MyEnum)x.RecordTypeID).ToString()
});
Select is a LINQ extension method and works on all IEnumerable<> objects whereas ConvertAll is implemented only by List<>. The ConvertAll method exists since .NET 2.0 whereas LINQ was introduced with 3.5.
You should favor Select over ConvertAll as it works for any kind of list, but they do the same basically.
I believe you have each switch statement for each MyEnum value?
That is a lot of repeated code, that's true.
Why don't you just convert int to text value directly?
You can do it like this for more readability
foreach(Record r in List<Record>)
{
MyEnum myEnum = (MyEnum)r.RecordTypeID;
string stringValue = myEnum .ToString();
listofRecordModified.Add(new RecordModified{RecordTypeID=r.RecordTypeID, ...,**RecordTypeText=stringValue })** // Notice this
}

how to create a calculating property

say i have a some properties
public int redBalls { get; set; }
public int blueBalls { get; set; }
I now want to have a totalBalls property which will add the two.
Would I do this?
public int totalBalls { get { return redBalls + blueBalls; } }
I'm trying this but the result is 0
*edit, i've spoken to my lead developer and it's because whatever accesses totalBalls isn't notified of the changes of redBalls or blueBalls so it wont recalculate those values
So I have to do OnPropertyChanged("total")
Wrote a test for you... This succeeds for me.
[Test]
public void SO()
{
var testing = new Testing();
Assert.AreEqual(0, testing.RedBalls);
Assert.AreEqual(0, testing.BlueBalls);
Assert.AreEqual(0, testing.TotalBalls);
testing.RedBalls = 2;
testing.BlueBalls = 4;
Assert.AreEqual(2, testing.RedBalls);
Assert.AreEqual(4, testing.BlueBalls);
Assert.AreEqual(6, testing.TotalBalls);
}
class Testing
{
public int RedBalls { get; set; }
public int BlueBalls { get; set; }
public int TotalBalls { get { return RedBalls + BlueBalls; } }
}
You must acutally set the value of redBalls/blueBalls
class Balls
{
public int redBalls { get; set; }
public int blueBalls{ get; set; }
public int totalBalls{ get{ return redBalls + blueBalls; } }
}
void test()
{
// You must acutally set the value of redBalls/blueBalls
var balls = new Balls{ redBalls = 1, blueBalls = 2 };
Assert.AreEqual(3, balls.totalBalls);
}
There is nothing wrong with your code except the capitalisation of the Property names, which is purely cosmetic.
totalBalls will = 0 whilst the sum of redBalls and blueBalls is 0, obviously, they will both = 0 until they are set to some other value.
EDIT
You didn't mention DependecyPropertys in the OP or the tags, if a dependecy property is bound to the totalBalls property it won't know that totalBalls is calculated from other properties.
You should extend the definition of your dependency property so that its metadata includes a PropertyChangedCallback that can detect the aggregated changes, rather than coupling your simple class to WPF.

Categories