declare variable as a field of the class [duplicate] - c#

This question already has answers here:
Use a variable from another method in C#
(2 answers)
Closed 5 years ago.
Using C#
This is a basic question I'm sure. I'm getting the error.. "The name '_stocks' does not exist in the current context". I know this is because I declared the _stocks dictionary within the Initialize method. This makes the _stocks variable a local variable and only accessible within the Initialize method. I need to declare the _stocks variable as a field of the class (so it can be accessed by any method of the class). The other method as you will see below is OnBarUpdate(). How do I go about declaring the _stocks variable as a field of the class?
public class MAcrossLong : Strategy
{
//Variables
private int variable1 = 0
private int variable2 = 0
public struct StockEntry
{
public string Name { get; set; }
public PeriodType Period { get; set; }
public int Value { get; set; }
public int Count { get; set; }
}
protected override void Initialize()
{
Dictionary<string, StockEntry> _stocks = new Dictionary<string, StockEntry>();
_stocks.Add("ABC", new StockEntry { Name = "ABC", Period = PeriodType.Minute, Value = 5, Count = 0 } );
}
protected override void OnBarUpdate()
{
//_stocks dictionary is used within the code in this method. error is occurring within this method
}
}
**Added Portion....
I should probably just post the code within OnBarUpdate() because I'm now getting other errors...
The best overloaded method match for 'System.Collections.Generic.Dictionary.this[string]' has some invalid arguments
Argument '1': cannot convert from 'int' to 'string'
Operator '<' cannot be applied to operands of type 'NinjaTrader.Strategy.MAcrossLong.StockEntry' and 'int'
protected override void OnBarUpdate()
{ //for loop to iterate each instrument through
for (int series = 0; series < 5; series++)
if (BarsInProgress == series)
{
var singleStockCount = _stocks[series];
bool enterTrade = false;
if (singleStockCount < 1)
{
enterTrade = true;
}
else
{
enterTrade = BarsSinceEntry(series, "", 0) > 2;
}
if (enterTrade)
{ // Condition for Long Entry here
EnterLong(200);
{
if(_stocks.ContainsKey(series))
{
_stocks[series]++;
}
}
}
}
}

You need to declare _stocks in a class level scope. Since you have declared it within the Initialize method its visibility becomes local to that method. So you should declare it along with variable1 and variable2 like
private int variable1 = 0;
private int variable2 = 0;
private Dictionary<string, StockEntry> _stocks;
You might need to look into the Access modifiers and Variable and Method Scopes for a better understanding

The same way you declared variable1 and variable2....
public class MAcrossLong : Strategy
{
private int variable1 = 0;
private int variable2 = 0;
private Dictionary<string, StockEntry> _stocks;
protected override void Initialize()
{
_stocks.Add("ABC", new StockEntry { Name = "ABC", Period = PeriodType.Minute, Value = 5, Count = 0 } );
}
protected override void OnBarUpdate()
{
_stocks["ABC"].Name = "new name"; // Or some other code with _stocks
}
}
To fix the error inside the OnBarUpdate() that you recently added, you need to switch to a foreach loop and use a KeyValuePair<string, StockEntry> iterator. You can read more on them here, here, and here.
It should look something like this:
foreach(KeyValuePair<string, StockEntry> stock in _stocks)
{
string ticker = stock.Key;
StockEntry stockEntry = stock.Value;
// Or some other actions with stock
}

Related

How would I find the value of an unspecified variable in other objects of the same class? C#

I want this method to work with any variable - i.e., passing a "Price" value to the method then getting the total price of all items.
private int GetTotalValue(int stat){
int total = 0;
foreach(Item i in Vendor.items){
totalStat += i.stat;
}
return total;
}
However, it has no way of knowing the name of the variable that I passed as the parameter, and thus no way of accessing it in other objects.
How would I tell the method what variable I'm passing, instead of just the value of it?
If you always want the sum of some property value you could encapsulate that logic into a method, e.g. GetVendorItemSum:
internal class Program
{
private static void Main(string[] args)
{
var items = new[] {
new Item {Price = 1},
new Item {Price = 2}
};
var vendor = new Vendor {Items = items};
var vendorSum = GetVendorItemsSum(vendor, x => x.Price);
}
private static int GetVendorItemsSum(Vendor vendor, Func<Item, int> func)
{
return vendor.Items.Sum(func);
}
}
public class Vendor
{
public IEnumerable<Item> Items;
}
public class Item
{
public int Price { get; set; }
}

How shouldi avoid the CS0120 error in my code? [duplicate]

This question already has answers here:
CS0120: An object reference is required for the nonstatic field, method, or property 'foo'
(9 answers)
Closed 5 years ago.
First i'll give you a run around my code,
I have a class that stores some data :
public class Balta
{
public int x;
public int y;
public int raza;
public int cantApa;
public int id;
public int intersect;
public Balta(int xs, int ys, int r, int cApa, int ids, int intersctt)
{
x = xs;
y = ys;
raza = r;
cantApa = cApa;
id = ids;
intersect = intersctt;
}
}
Secondly I have a class that makes a list of that data and stores it acordingly,also i intend to do some operations with that data once i get rid of this pesky error.
public class Baltile
{
public int n;
List<Balta> balti = new List<Balta>();
public void populate(Balta balta)
{
int unitId = balta.id;
if (balti.Any(Balta => Balta.id == balta.id))
{
int pos = balti.FindIndex(Balta => Balta.id == balta.id);
balti[pos] = balta;
}
else if (balti.Any(Balta => Balta.cantApa == -1) && !balti.Any(Balta => Balta.id == unitId))
{
int pos = balti.FindIndex(Balta => Balta.cantApa == -1);
balti[pos] = balta;
}
else //daca nu inseamna ca aduaugi balta la lista
{
balti.Add(balta);
}
}
}
And main looks something like this
static void Main(string[] args)
{
Baltile balti = new Baltile();
while (true)
{
"data input block"
for (int i = 0; i < unitCount; i++)
{
"more data input"
if (i>2)
{
Balta balta = new Balta(x, y, radius, extra, unitId, 0);
Baltile.populate(balta);//the CS0120 error is here
}
}
}
}
So CS0120 tells me this An object reference is required for the non-static field, method, or property.This means main is static so i cant call a non static method if i understood right ? Declaring everything static will give even more errors.
How should i go around this ? I cant seem to figure out how to make my code work ?
With
Baltile.populate(balta);
and Baltile being a class name, this would require populate() to be a static method.
As per MSDN, the full error message is
Compiler Error CS0120
An object reference is required for the nonstatic field, method, or
property 'member'
This tells you to use an object instead of a class. And it seems you already have an object called balti that serves this purpose. So use
balti.populate(balta);
instead. Now you call the populate() method on an instance (an object) instead of the class.

In a Dictionary TryGetValue, how do I write the out parameter (and get it's values) if it's part of a class?

Past question thread and link to fullpast code HERE
I create my dictionary with a class for a parameter so it can hold two string values. Now I'm trying to write a TryGetValue to out both of the strings in this class:
public class DictionaryInitializer
{
public class DictionarySetup
{
public string theDescription { get; set; }
public string theClass { get; set; }
}
As you can see, there's theDescription and theClass nested in the DictionarySetup. Then I would create the dictionaries using that class here:
public class DictionaryInit
{
//IS_Revenues data
public Dictionary<int, DictionarySetup> accountRevenue = new Dictionary<int, DictionarySetup>()
{
{ 400000, new DictionarySetup {theDescription="Call", theClass="Revenues"}}
};
public Dictionary<int, DictionarySetup> accountExpenses = new Dictionary<int, DictionarySetup>()
{
{790100, new DictionarySetup { theDescription="Currency Hedge", theClass="Other income/expense"}}
};
}
Then, my extension method where I plan to use my TryGetValue on the dictionary:
public void DictionaryUseKey(int MapCode, int MapKey, int rowindex, Dictionary<int, DictionarySetup> AccountLexicon)
{
AccountLexicon[1] = new DictionarySetup();
DictionarySetup Classes;
DictionarySetup Descriptions;
//Saw the above code in another thread, not sure if it's what I should be doing but it seems pretty close to what I want, however, I don't know how to specify the DictionarySetup.theDescription for example;
AccountLexicon.TryGetValue(MapKey, out Classes);
{
//I want to be able to write theDescription and theClass into string variables for use below if the `TryGetValue` returns true, but it seems to me that it can only out one value? How does this work?
DGVMain.Rows[rowindex].Cells[3].Value = ?? how do I write something like... theValues.theDescription;
DGVMain.Rows[rowindex].Cells[11].Value = ?? how do I write something like... theValues.theClass;
}
}
Lastly, I call the extension method in my event like so:
private void btnMapper_Click(object sender, EventArgs e)
{
for (int rowindex = 0; rowindex < DGVMain.RowCount; rowindex++)
{
int accountKey = Convert.ToInt32(DGVMain.Rows[rowindex].Cells[2].Value);
int projCode = Math.Abs(Convert.ToInt32(DGVMain.Rows[rowindex].Cells[7].Value));
int deptCode = Math.Abs(Convert.ToInt32(DGVMain.Rows[rowindex].Cells[9].Value));
int AbsoluteKey = Math.Abs(accountKey);
while (AbsoluteKey >= 10) { AbsoluteKey /= 10; }
while (deptCode >= 10) { deptCode /= 10; }
theDictionary = new DictionaryInit();
DictionaryUseKey(deptCode, accountKey, theDictionary.accountRevenue);
}
}
Actually the TryGetValue method will returns a boolean value represents the presence of the specified key, if the key is found, the corresponding value will be stored in the out parameter. Here in your case the out parameter is Classes and are defined in your code like this: DictionarySetup Classes. which means in case the key is present in the Dictionary means corresponding DictionarySetup object will be stored in the Classes so you can access the theDescription and theClass from Classes; Consider the code below:
if(AccountLexicon.TryGetValue(MapKey, out Classes))
{
DGVMain.Rows[rowindex].Cells[3].Value = Classes.theDescription;
DGVMain.Rows[rowindex].Cells[11].Value = Classes.theClass;
}

Cannot add an item to a List in a constructor of a user control's base class

I seem to be getting a null reference error when I try to add an item to a list in the constructor of my CustomCheckoutProcess class. This class is inherited by a user control's class, so its default constructor is called when the control's constructor is called (I believe that's how it works).
Here's the relevant parts of the class definition for the checkout process (error seems to be line 12 - marked with a comment on line 11):
public class CustomShoppingCart : ShoppingCart {
private List<CheckoutProcessArgument> checkoutProcessArguments = List<CheckoutProcessArgument>();
public CustomShoppingCart()
{
GetBaseCartSteps();
CheckoutProcessArgument stepTwoArg = new CheckoutProcessArgument("Step2", new Guid("12345678-1234-1234-1234-123456789012"));
// when I comment this line out, everything works fine
checkoutProcessArguments.Add(stepTwoArg);
BuildCheckoutProcess();
}
private void GetBaseCartSteps()
{
baseCartSteps = new Dictionary<string, int>();
// iterate through base cart's steps and grab name/index pairs
foreach (CheckoutProcessStepInfo step in this.CheckoutProcessSteps)
{
baseCartSteps.Add(step.Name, step.StepIndex);
}
}
private bool CartContains(Guid productGuid)
{
for (int i = 0; i < ShoppingCartInfoObj.CartItems.Count; i++)
{
if (ShoppingCartInfoObj.CartItems[i].SKU.SKUGUID == productGuid)
{
return true;
}
}
return false;
}
private void BuildCheckoutProcess()
{
// create a list of ints to dynamically add or remove the indexes of the base cart's steps
List<int> steps = new List<int>();
if (checkoutProcessArguments != null)
{
// add steps if they are specified in the arguments list
foreach (CheckoutProcessArgument argument in checkoutProcessArguments)
{
if (CartContains(argument.ProductGUID))
{
int stepIndexToAdd;
baseCartSteps.TryGetValue(argument.StepName, out stepIndexToAdd);
steps.Add(stepIndexToAdd);
}
}
}
// sort the steps so that they'll be in the correct order
steps.Sort();
customSteps = new int[steps.Count];
customSteps = steps.ToArray();
}
}
And here's the struct that I'm using to create arguments for a custom checkout process:
public struct CheckoutProcessArgument
{
private string stepName;
private Guid productGUID;
public string StepName { get { return stepName; } }
public Guid ProductGUID { get { return productGUID; } }
public CheckoutProcessArgument(string stepName, Guid productGuid)
{
this.stepName = stepName;
this.productGUID = productGuid;
}
}
Here's the stack trace for the error I recieve:
Message: Object reference not set to an instance of an object.
Stack Trace:
at CustomShoppingCart..ctor()
...
Problem is, I can't seem to see what could possibly be null. Any ideas? I'm guessing the problem isn't that I'm adding something to a List in a constructor, but that I've bungled something else somewhere, but for the life of me I can't figure out what.
Try instantianting the list in the constructor immediately before you attempt to access it. Also, if the list is to not be assigned to again you can use the readonly keyword. Further note that we can instantiate the list and add stepTwoArg to it in a single line of code.
private readonly List<CheckoutProcessArgument> checkoutProcessArguments;
public CustomShoppingCart()
{
GetBaseCartSteps();
CheckoutProcessArgument stepTwoArg = new CheckoutProcessArgument("Step2", new Guid("12345678-1234-1234-1234-123456789012"));
checkoutProcessArguments = new List<CheckoutProcessArgument> { stepTwoArg };
BuildCheckoutProcess();
}

Can properties inside an object initializer reference each other?

Is it somehow possible for properties to reference each other during the creation of a dynamic object an anonymously-typed object (i.e. inside the object initializer)? My simplified example below needs to reuse the Age property without making a second heavy call to GetAgeFromSomewhere(). Of course it doesn't work. Any suggestion on how to accomplish this?
var profile = new {
Age = GetAgeFromSomewhere(id),
IsLegal = (Age>18)
};
Is something like this possible or not possible with dynamic objects anonymously-typed object initializers?
Unfortunately it's not possible, even with explicitly typed objects. This is because of the way object initializers work. For example:
public class MyClass
{
public int Age = 10;
public bool IsLegal = Age > 18;
}
Yields this compiler error at "IsLegal":
Error 1 A field initializer cannot reference the non-static field,
method, or property 'MyClass.Age' ...
Field initializer can't reference other non-static fields, and since anonymous types don't create static fields, you can't use the value of one field to initialize another. The only way around this, is to declare the variables outside the anonymous type and use them inside the initializer.
int age = GetAgeFromSomewhere(id);
var profile = new {
Age = age,
IsLegal = age > 18
};
Don't complicate thing, keep it simple
//Create a variable
var age = GetAgeFromSomewhere(id);
var profile = new {
Age = age,
IsLegal = age>18
}
What you want is not possible within object intializers. You cannot read properties of the object being initialized. (It does not matter, whether the type is anonymous or not.)
Instead, Create a class
public class Profile
{
public Profile(int id)
{
Age = GetAgeFromSomewhere(id);
}
public int Age { get; private set; }
public int IsLegal { get { return Age > 18; } }
}
Or getting the age the lazy way:
public class Profile
{
private readonly int _id;
public Profile(int id)
{
_id = id;
}
private int? _age;
public int Age {
get {
if (_age == null) {
_age = GetAgeFromSomewhere(_id);
}
return _age.Value;
}
}
public int IsLegal { get { return Age > 18; } }
}
or using the Lazy<T> class (starting with Framework 4.0):
public class Profile
{
public Profile(int id)
{
// C# captures the `id` in a closure.
_lazyAge = new Lazy<int>(
() => GetAgeFromSomewhere(id)
);
}
private Lazy<int> _lazyAge;
public int Age { get { return _lazyAge.Value; } }
public int IsLegal { get { return Age > 18; } }
}
Call it like this
var profile = new Profile(id);
If you don't want to have unnecessary variable, I suggest you use the current object instead :
var profile = new
{
Age = GetAgeFromSomewhere(id),
};
profile.IsLegal = profile.Age > 18;

Categories

Resources