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.
I've defined a function in a class like this.
In this class, a value is either looked up or calculated if not found among a list of already calculate values.
If calculated anew, the result is stored in a list so that I can look it up in subsequent calls.
The problem is that the compiler doesn't like the way I do it and tells me
An object reference is required for the non-static field, method or property App.GetGoodFontSize(string, Size).
I don't understand what the compiler suggests. Which object reference does it mean?
Thank you.
public class App : Application
{
private List<udt> _list = new List<udt>();
private class udt
{
public int iLen { get; set; }
public Size nSize { get; set; }
public double FontSize { get; set; }
}
public double GetGoodFontSize(string uText, Xamarin.Forms.Size uTextRect)
{
for (int i = 0; i < _list.Count; i++)
{
if ((_list[i].iLen == uText.Length) && (_list[i].nSize == uTextRect))
{
return _list[i].FontSize;
}
}
int iBest = 100;
for (int i = 100; i > 6; i--)
{
Size nSize = GetTextSize(uText, i);
if (nSize.Width <= uTextRect.Width)
{
if (nSize.Height <= uTextRect.Height)
{
iBest = i;
break;
}
}
}
udt n = new udt();
n.iLen = uText.Length;
n.nSize = uTextRect;
n.FontSize = iBest;
_list.Add(n);
return iBest;
}
Change your code like this:
public static double GetGoodFontSize(string uText, Xamarin.Forms.Size uTextRect)
private static List<udt> _list = new List<udt>();
Related
This question already has answers here:
Difference between a List's Add and Append method?
(2 answers)
Closed 4 months ago.
https://dotnetfiddle.net/QHd0Rr#
I'm trying to populate a simple IEnumerable but I'm getting an error:
Unhandled exception. System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
at System.Collections.Generic.List`1.get_Item(Int32 index)
at Program.Main()
Command terminated by signal 6
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var key1 = new WidgetA{Id = 1, Key = 52};
var key2 = new WidgetA{Id = 1, Key = 102};
var key3 = new WidgetA{Id = 1, Key = 152};
IEnumerable<WidgetA> list = Enumerable.Empty<WidgetA>();
list.Append(key1);
list.Append(key2);
list.Append(key3);
Console.WriteLine(list.ToList()[0]);
}
}
public class WidgetA
{
public int Id { get; set; }
public int Key { get; set; }
public string ValueToGet { get; set; }
}
Enumerable.Append<> is a lazy Linq function. If this is how you want to use it, you need to store the intermediate result:
IEnumerable<WidgetA> list = Enumerable.Empty<WidgetA>();
list = list.Append(key1);
list = list.Append(key2);
list = list.Append(key3);
While I really like (and upvoted) Blindy's answer and I think that it may better fit your need, here is an alternative with yield return:
public static void Main()
{
IEnumerable<int> list = DoStuff();
list.Dump();
}
public static IEnumerable<int> DoStuff()
{
yield return 0;
yield return 1;
// enter code here or whatever
yield return 2;
yield return 3;
yield return 4;
}
i want do some action if value of property in object is equal something.
My object:
//abstract class Tile.cs
namespace DungeonGame.Tiles
{
public abstract class Tile
{
public abstract string Type { get; set; }
}
}
//Item.cs that iherits from Tile.cs
namespace DungeonGame
{
public class Item : Tile
{
public override string Type { get; set; }
public string Name { get; set; }
public Item(string name)
{
this.Type = "item";
this.Name = name;
}
}
}
And i have several objects in public Object[,] BoardTiles { get; private set; }, I had to store different types of tiles in same place so i had to use Object type array.
What i'm trying to do is replace array index with different type of object, depending of the value of property (In this case I set value depending of object type not his value of property):
public void movefillRight(int playerPositionRowIndex, int playerPositionColumnIndex)
{
for (int r = 0; r < Rows; r++)
{
for (int c = 0; c < Cols; c++)
{
if (BoardTiles[playerPositionRowIndex, playerPositionColumnIndex ].GetType().ToString() == ("DungeonGame.Item"))
{
/* placePlayerOnTheBoard(playerPositionRowIndex, playerPositionColumnIndex, PlayerTile);
*/ BoardTiles[playerPositionRowIndex, playerPositionColumnIndex] = Item1;
BoardTiles[playerPositionRowIndex, playerPositionColumnIndex - 1] = Floor;
}
else if (BoardTiles[playerPositionRowIndex, playerPositionColumnIndex-1].GetType().ToString() == ("DungeonGame.Item"))
{
BoardTiles[playerPositionRowIndex, playerPositionColumnIndex-1] = Item1;
placePlayerOnTheBoard(playerPositionRowIndex, playerPositionColumnIndex, PlayerTile);
}
else
{
placePlayerOnTheBoard(playerPositionRowIndex, playerPositionColumnIndex, PlayerTile);
BoardTiles[playerPositionRowIndex, playerPositionColumnIndex - 1] = Floor;
}
}
}
Console.WriteLine(BoardTiles[playerPositionRowIndex, playerPositionColumnIndex].GetType().ToString());//log
}
The functionality of the function is to leave the same object on the same index when the player walks over it, so the problem is that code is ok when I have one Item, for example only sword, but when there are more items i can replace index always with same object but not with object witch different properties, when the player walks over a good sword and bad sword (same object, but another properties) he leave behind just sword... I have idea how to solve this problem but i need to refer to property value which is at specific index of my object array.
After you check that the item in the array is of a specific type you can then cast it.
if (BoardTiles[playerPositionRowIndex, playerPositionColumnIndex ].GetType().ToString() == ("DungeonGame.Item"))
{
var item = (DungeonGame.Item)BoardTiles[playerPositionRowIndex, playerPositionColumnIndex];
Console.Writeline(item.Name);
}
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
I have built a simple code as shown below. While debugging, I am getting an error about "NullReference Handled Exception" at the code line:
X.DataPoints.Add(dp);
Here is the code snippet. Please advice on what am I missing?
public class RankPlot
{
public List<RankPlotDataPoint> DataPoints { get; set; }
}
public class RankPlotDataPoint
{
public double RankVal { get; set; }
public double ProbVal { get; set; }
}
ObservableCollection<RankPlot> EURresults = new ObservableCollection<RankPlot>();
public ObservableCollection<RankPlot> EURResults
{
get { return EURresults; }
set
{
EURresults = value;
base.OnPropertyChanged("StringList");
}
}
public void evaluate()
{
RankPlot X = new RankPlot();
for (double i = 0; i<5; i++)
{
RankPlotDataPoint dp = new RankPlotDataPoint();
dp.RankVal =i+1; // Y axis
dp.ProbVal = i; // X axis
X.DataPoints.Add(dp);
}
EURResults.Add(X);
}
You are getting Null Exception Because you need to initialize the List<RankPlotDataPoint> DataPoints. So Instead of Initialize DataPoints every time you create an instance of RankPlot, you should initialize like below:
Change your Below Statement:
public class RankPlot
{
public List<RankPlotDataPoint> DataPoints { get; set; }
}
To
public class RankPlot
{
public List<RankPlotDataPoint> DataPoints { get; set; } = new List<RankPlotDataPoint>();
}
in evaluate() method instead of
RankPlot X = new RankPlot();
write
RankPlot X = new RankPlot{DataPoints = new List<RankPlotDataPoint>()};
It'll initialize the list.
X.DataPoints = new List<RankPlotDataPoint>(); you never initialize the list before you add items to the list.
You are trying to add a value to a List<RankPlotData> that doesn't exist. With your property in the RankPlot class, you need to declare a new List of RankPlotData in your RankPlot class, and initialize it with .. new List<RankPlotData>(). Then, you should return that from your property get accessor.
I want correctly return some variables (arrays)
kazkas.Ads[n]; (n = how many ads are)
kazkas.Ads[n].id;
kazkas.Ads[n].Days[m].Stats.Clicks; // every day have his own clicks
kazkas.Ads[n].Days[m].Stats.Impresons; // every day have his own impresions
from this method and use these variables in other class.
public static void GetAdsStats(string Ticket, DateTime start, DateTime end, int CamId)
{
var client = new CampaignStatsServiceClient();
var id = new CampaignIdFilter();
id.CampaignId = CamId;
var statsdata = new GetAdStatsData();
var kazkas = new Campaign();
kazkas = client.GetAdStats(Ticket, new GetAdStatsData
{
IdFilter = id,
StartDate = start,
EndDate = end
});
long AllClicks = 0;
long AllImpresions = 0;
int reklamos = kazkas.Ads.Length;
long[] statistikaClikai = new long[reklamos];
long[] statistikaImpresions = new long[reklamos];
for (int i = 0; i < reklamos; i++)
{
int dienos = kazkas.Ads[i].Days.Length;
for (int lop = 0; lop < dienos; lop++)
{
AllClicks = AllClicks + kazkas.Ads[i].Days[lop].Stats.Clicks;
AllImpresions = AllImpresions + kazkas.Ads[i].Days[lop].Stats.Impressions;
}
statistikaClikai[i] = AllClicks;
statistikaImpresions[i] = AllImpresions;
}
}
I know that void type can't return anything, but this how I know that my method works ( from debugging). Like you see I was trying do that with for loop. Here i have 9 Ads and every ad have one day.
Like I says I want return every Ads id[in array], and every days.stats.impresions and days.stats.click
how can I do that ? Ore how return more variables/arrays from method to other class, I am using webservises, so i cant use database ore something like that.
As can be seen by the downvotes of the question, you need to design the return value and then code against it.
Your query almost does it (now):
kazkas.Ads[n]; (n = how many ads are)
kazkas.Ads[n].id;
kazkas.Ads[n].Days[m].Stats.Clicks; // every day have his own clicks
kazkas.Ads[n].Days[m].Stats.Impressions; // every day have his own impressions
Your existing code show this should be expanded to include:
kazkas.Ads[n].Total.Clicks;
kazkas.Ads[n].Total.Impressions;
So now you're ready to design. First you want a Stat Class that just contains CLicks and Impressions:
public class Stat
{
public long Impressions { get; set; }
public long Clicks { get; set; }
}
An optimisation here may be to use a struct, but I won't go into that.
As you currently have defined it each Day has just a Stats property:
public class DayStat
{
public Stat Stats { get; set; }
}
Now finally we can define the top level AdStat:
public class AdStat
{
public int id { get; set; }
public DayStat Day[];
public Stat Total { get; set; }
}
Etc... There's further issues here, such as ensuring arrays are created and Stat instances are never null (which is why making some of these classes structs is an option). But I'm really a VB programmer so I'll stop here before I get caught typing crap into the SO IDE :-)
Create a class or struct with members you need
public class Stat
{
public int Id { get; set; }
public long Clicks { get; set; }
...
}
Change the signature of your method from void GetAdsStats to IEnumberable<Stat> GetAdsStats and either return a collection of stats or use yield keyword to return the stat object.
Also if you do not want your method to return anything (return type void) do not use a name starting with Get.
Example:
public static IEnumerable<Stat> GetAdsStats(...)
{
...
var statList = new List<Stat>();
for (int i = 0; i < reklamos; i++)
{
var stat = new Stat();
statList.Add(stat);
int dienos = kazkas.Ads[i].Days.Length;
for (int lop = 0; lop < dienos; lop++)
{
AllClicks = AllClicks + kazkas.Ads[i].Days[lop].Stats.Clicks;
AllImpresions = AllImpresions + kazkas.Ads[i].Days[lop].Stats.Impressions;
}
stat.Clicks = AllClicks;
stat.Impression = AllImpresions;
}
return statList;
}
Change your void to the type you want to return, say Campaign, and return the appropriate variable. The variables you define in your method, only live in your method and are not accessible from another method or class.
How to pass by ref different types of objects that have the same properties inside and populate them without interface.
In my app there are totally different types which have some properties in common.
Let's say this properties are double arrays.
double[] samples;
Now I have to populate these samples for 20 objects.
I don't have any access to the class definition of this object, so I can't make interface, or make them inherit from a base class.
How can use one method which I call and this method to populate all my properties.
I want to have one method like this:
private static void FillSamples(ref WhoKnowsWhat dataType, MyObject theSamples)
{
for (int i = 0; i < sampleCount; i++)
{
dataType.SampleLength[i] = MyObject.X[i];
dataType.SampleValue[i] = MyObject.y[i];
}
}
And call this with totally different types.
FillSamples(ref BigStruct.OneTypeMine, theSamples);
FillSamples(ref BigStruct.AnotherTypeMine, theSamples);
FillSamples(ref BigStruct.HisType12345, theSamples);
Then the big struct should have these samples filled in the end.
Is there a way in C#?
Thanks!
You can use the dynamic keyword:
private static void FillSamples(dynamic dataType, MyObject theSamples)
{
for (int i = 0; i < sampleCount; i++)
{
dataType.SampleLength[i] = MyObject.X[i];
dataType.SampleValue[i] = MyObject.y[i];
}
}
Edit:
Using reflection (if you don't use .Net 4.0 or higher):
private static void FillSamples(object dataType, MyObject theSamples)
{
Type t = dataType.GetType();
var px = t.GetProperty("SampleLength");
var py = t.GetProperty("SampleValue");
for (int i = 0; i < sampleCount; i++)
{
px.SetValue(dataType, MyObject.X[i], null);
py.SetValue(dataType, MyObject.Y[i], null);
}
}
Don't know if it helps you any, but you can use reflection to find out what properties (and fields, methods etc.) an object supports at runtime. Check out http://www.csharp-examples.net/reflection-property-names/ for example, if you're interested in learning more.
You can use dynamic objects. You should be careful when targeting fields of a dynamic object since they cannot be checked at compile time. See my example below:
[TestFixture]
public class DynamicObjects
{
[Test]
public void Dynamic_Call()
{
dynamic obj1 = new Apple();
obj1.Weight = 100;
obj1.Color = "Red";
dynamic obj2 = new Orange();
obj2.Weight = 200;
obj2.Width = 10;
Assert.IsTrue(obj1.Weight < obj2.Weight);
}
}
public class Apple
{
public int Weight { get; set; }
public string Color { get; set; }
}
public class Orange
{
public int Weight { get; set; }
public int Width { get; set; }
}