I'm fairly new to C# and I have just learned about creating custom classes. The problem is, I can't figure out how to take the 40~65 instances of this class and put them in a list/array (whichever one I need) where I can locate and choose one based on an attribute defined in it.
Here's the class I have created right now:
public class Team
{
protected int teamNum;
protected double averageMatchPoints;
protected string location;
protected int matchesPlayed;
protected int matchesPending;
protected int blowouts;
//Team Number
public void SetNumber(int num)
{
teamNum = num;
}
public int GetNumber()
{
return teamNum;
}
//Average Points per match
public void AverageMatchPoints(double p)
{
averageMatchPoints = p;
}
public double GetAverageMatchPoints()
{
return averageMatchPoints;
}
//location information
public void SetLocation(string l)
{
location = l;
}
public string GetLocation()
{
return location;
}
//Number of Played Matches
public void PlayedMatches(int mat)
{
matchesPlayed = mat;
}
public int GetPlayedMatches()
{
return matchesPlayed;
}
//Number of matches pending (not played)
public void PendingMatches(int pen)
{
matchesPending = pen;
}
public int GetPendingMatches()
{
return matchesPending;
}
//Number of Blowouts (matches where the robot was disbaled for any number of reasons)
public void SetBlowouts(int b)
{
blowouts = b;
}
public int GetBlowouts()
{
return blowouts;
}
}
Now, if I had 40~65 of these teams competing at an event and I made an instance of this class for each one, how would I populate a combobox with each team number (teamNum) and then locate one specific team out of all the instances in the program by their team numbers?
I recommend a dictionary!
// Declared somewhere
private Dictionary<int, Team> _teamDictionary = new Dictionary<int, Team>();
.
.
.
//Initialization code - I assume you have gotten your teams from a database or somewhere?
foreach (var team in myTeamsList)
{
_teamDictionary.Add(team.teamNum, team);
}
.
.
.
// Later when you want to locate a team:
var team = _teamDictionary[selectedTeamNum];
Have you tried creating a List yet?
List<Team> Teams { get; set; }
You can then bind your combobox to the list/collection/IEnumerable of all the teams that you have. To initialize the teams up to 40/60 do the following?
for(int i = 0; i < 60; i++)
{
Team t = new Team();
t.Name = "Team 1";
t.TeamNumber = i + 1;
Teams.Add(t);
}
List<Team> allTheTeams = new List<Team>();
for(var i = 0; i < 65; i++){
allTheTeams.Add(new Team { teamNum = i });
}
And to get the team with number 34:
allTheTeams.FirstOrDefault(x => x.teamNum == 34);
Like this:
Add a constructor to your class that takes the teamnumber:
(this is the best solution if every team needs to have a number. So you can not forget to set the team number as you can not create an object of type team without setting the number in the constructor)
public class Team
{
protected int _teamNum;
public Team(int teamNum)
{
_teamNum = teamNum;
}
public int getTeamNum()
{
return _teamNum;
}
//more logic
}
Populate a dictionary, the comboBox and get a team for its number:
Dictionary<int, Team> dictionary = new Dictionary<int, Team>();
int teamNum = 1;
// Add your Teams to a dictionary (example)
dictionary.Add(teamNum ,new Team(teamNum++));
dictionary.Add(teamNum, new Team(teamNum++));
dictionary.Add(teamNum, new Team(teamNum++));
// Populate a comboBox
foreach(KeyValuePair<int,Team> kvp in dictionary)
{
comboBox1.Items.Add(kvp.Value.getTeamNum().ToString());
}
// get a team for a given teamNumer
int targetTeamNumber = 2;
if (dictionary.ContainsKey(targetTeamNumber))
{
Team team = dictionary[targetTeamNumber];
// do something with the team
}
Related
I am currently making an application which tracks information on players and monsters for a tabletop game.
Currently I've got classes for "Monsters". This class contains information such as its name, maxHP, speed, attacks etc. I've managed to make a Database which contains the default values for each type of monster. What I currently need to do is make it possible to change things such as name (Monster > Monster 1, Monster 2 etc), change its HP, and some other things.
I understand that I need to make a copy of such, but I am uncertain on how to do this.
What I currently tried is the following:
public class DatabaseService
{
public List<Player> Players { get; set; }
public List<Monster> AllMonsters { get; set; }
public List<Monster> ActiveMonsters = new List<Monster>();
public bool RollForHP = false;
//Main Database Service
public DatabaseService()
{
Players = GetPlayers();
AllMonsters = GetAllMonsters();
}
public void DoStuff()
{
AddMonsterByName("Goblin", 2);
AddMonsterByName("Adult White Dragon", 1);
AddMonsterByName("Duergar", 4);
foreach (Monster monster in ActiveMonsters) { Console.WriteLine(monster.Name); }
}
//Converts the .json list with all players to Classes, which are then stored in the list "Players" if the "IsInParty" is true
private List<Player> GetPlayers()
{
var path = #"C:\Users\MyName\source\repos\DndAdvancedInitiativeTracker\Logic\Database\Players.json";
var json = File.ReadAllText(path);
var players = JsonConvert.DeserializeObject<List<Player>>(json);
List<Player> inPartyPlayers = new List<Player>();
foreach (var player in players)
{
if (player.IsInParty == true) { inPartyPlayers.Add(player); }
}
return inPartyPlayers;
}
//Converts the .json list with all monsters to Classes, which are then stored in the list "AllMonsters"
private List<Monster> GetAllMonsters()
{
var path = #"C:\Users\MyName\source\repos\DndAdvancedInitiativeTracker\Logic\Database\Monsters.json";
var json = File.ReadAllText(path);
var monsters = JsonConvert.DeserializeObject<List<Monster>>(json);
return monsters;
}
//Adds a given monster to the "ActiveMonsters" list
public void AddMonsterByName(string monsterName, int amountOfMonsters)
{
for (int i = 0; i < amountOfMonsters; i++)
{
List<Monster> DatabaseCopy = AllMonsters.Clone();
DatabaseCopy = AllMonsters;
Monster monster = DatabaseCopy.Find(x => x.Name == monsterName);
Console.WriteLine(monster.Name);
var number = CheckIfNameExistsInList(monsterName);
monster.Name = monsterName + " " + (number + i).ToString();
ActiveMonsters.Add(monster);
}
}
private int CheckIfNameExistsInList(string monsterName)
{
var counter = 1;
foreach (var monster in ActiveMonsters)
{
if (monster.Name.Contains(monsterName))
{
counter += 1;
}
}
return counter;
}
}
In the "DoStuff" Method, I try to add 2 goblins, then a dragon, then a goblin again. The first goblin is named to "Goblin 1" correctly, but the second loop fails, because the AllMonsters' name for goblins is now "Goblin 1" because of the reference type, therefore, the second "Goblin" search in AllMonsters is never found, and returns null.
I'm not sure why you're copying your database (and doing so for every iteration of a for loop which is quite wasteful), but your current check code CheckIfNameExistsInList will always return 1 even if there are no matches in the list.
You can simplify your AddMonstersByName (and use a simple check for previous monster entries) as follows:
public void AddMonstersByName(string name, uint number = 1)
{
var count = AllMonsters.Count(x => x.Name.Contains(name));
for (var i = 1; i <= number; i++)
{
var num = count + i;
AllMonsters.Add(new Monster(){Name= name+num.ToString()});
}
}
This was tested in a simple Console App:
var dataService = new DataService();
dataService.AddMonstersByName("Goblin", 2);
dataService.AddMonstersByName("Dragon", 2);
dataService.AddMonstersByName("Goblin", 2);
foreach (var monster in dataService.AllMonsters)
{
Console.WriteLine($"{monster.Name}");
}
where
public class DataService
{
public List<Monster> AllMonsters = new List<Monster>();
public void AddMonstersByName(string name, uint number = 1)
{
var count = AllMonsters.Count(x => x.Name.Contains(name));
for (var i = 1; i <= number; i++)
{
var num = count + i;
AllMonsters.Add(new Monster(){Name= name+num.ToString()});
}
}
}
public class Monster
{
public string Name { get; set; }
}
I am slowly working through a project and I have encountered a problem, I would need both advice on what is the best course of action to choose.
I am using a triangle of type sides which the class is as follows
public class Sides
{
//These are the encapsulated data
private int intAdj; //adjacent
private int intOpp; //opposite
private Double doubleHypot; //hypotenuse
//This is the constructor
public Sides(int intAdj, int intOpp, Double doubleHypot)
{
//less confusion when the same name is used
this.intAdj = intAdj;
this.intOpp = intOpp;
this.doubleHypot = doubleHypot;
}
//Getters and Setters
public int IntAdj { get; set; }
public int IntOpp { get; set; }
private Double DoubleHypot { get; set; }
}
}
This is the declaration of the List
private List<Sides> listTriangle;
and it is initialised as follows:
listTriangle = new List<Sides>(); //Creates the list of type Sides
Here is where I am calling the calculations and the output
PerformCalc(intTriangleSize);
OutputList();
This is where I am performing the calculations and added to the list
private void PerformCalc(int intTriangleSize)
{
//This is where the calculations occur
for (int indexAdj = 1; indexAdj < (intTriangleSize + 1); indexAdj++)
{
for (int indexOpp = 1; indexOpp < (intTriangleSize + 1); indexOpp++)
{
doubleHypotenuse = doubHypot(doubleSquare(indexAdj), doubleSquare(indexOpp));
listTriangle.Add(new Sides(indexAdj, indexOpp, doubleHypotenuse));
}
}
}
I am now trying to output this list to through either a datagridview or a listview. they look like this:
and the output image is as follows
The code that I am using is as follows
private void OutputList()
{
DataTable myDataTable = new DataTable();
myDataTable.Columns.Add("Adjacent", System.Type.GetType("System.Int16"));
myDataTable.Columns.Add("Opposite", System.Type.GetType("System.Int16"));
myDataTable.Columns.Add("Hypotenuse", System.Type.GetType("System.Double"));
foreach (Sides myTriSides in listTriangle)
{
myDataTable.Rows.Add();
}
dataGridView1.DataSource = myDataTable;
for (int indexList = 0; indexList < listTriangle.Count(); indexList++)
{
listView1.Items.Add(listTriangle[indexList].IntAdj.ToString(),
listTriangle[indexList].IntOpp.ToString(),
listTriangle[indexList].DoubleHypot.ToString()) ;
}
}
I know there are issues with the code but I am not sure where the issue of the code is.
from my research it is split evenly with people advising datagridview and the listview. Can I get advise which is the better view to use in this case.
All help and advice would be greatly appreciated.
Suppose I have a list of Robot class [List< Robot> myList=new List< Robot>()]. Each Robot has a name and id depending on its colour. Now randomly pick values from the list and give an output of how many Robots of each colour are there on your list.
(N.B. Consider you have only 3 colored Robot[Yellow,green, red])
my code:
public class Test : MonoBehaviour
{
private void Start()
{
List<Robot> myList = new List<Robot>();
List<string> robotList = new List<string>();
robotList.Add("yellow");
robotList.Add("green");
robotList.Add("red");
int someNum = Random.Range(0, robotList.Count);
string robotNumber = robotList[someNum];
robotList.RemoveAt(someNum);
Robot robot;
int id = 0;
robot = new Robot(robotNumber, id);
Debug.Log(robot);
id++;
}
}
public class Robot
{
public string name;
public int id;
public Robot(string name, int id)
{
this.name = name;
this.id = id;
}
}
but this not work maybe.. actually I don't understand what actually my output is...
Not sure to really understand what you're asking for: if it's only about the meaning of the Debug.Log(robot); output, check for #Smartis answer as it answers it perfectly :)
Otherwise, I feel like you wanted to populate a List<Robot> with random picked names. In this case you need to use a loop: Start() method is only called once on start (as its name suggest). If you need to populate a list with random picked colors/names and then display how many of each colors/names are in the list you can do it as follow:
public class Test : MonoBehaviour
{
private void Start()
{
List<Robot> robotsList = new List<Robot>();
List<string> namesList = new List<string>();
namesList.Add("yellow");
namesList.Add("green");
namesList.Add("red");
PopulateRobotsList();
DisplayRobotsListContent();
}
private void PopulateRobotsList()
{
for(int id = 0; id < 100; id++)
{
string robotName = namesList[Random.Range(0, namesList.Count)];
robotsList.Add(new Robot(robotName, id));
//Debug.Log(robotsList[robotsList.Count - 1]);
}
}
private void DisplayRobotsListContent()
{
int[] robotsNamesCount = new int[namesList.Count];
for (int i = 0; i < robotsList.Count; i++)
{
robotsNamesCount[namesList.IndexOf(robotsList[i].name)] += 1;
}
for (int i = 0; i < namesList.Count; i++)
{
Debug.Log("Robot(s) named \"" + namesList[i] + "\" : " + robotsNamesCount[i]);
}
}
}
public class Robot
{
public string name;
public int id;
public Robot(string name, int id)
{
this.name = name;
this.id = id;
}
}
Please note I changed some variable names as I found it really hard to understand with the one you provided (ex: robotsList to store the potential colors/names of the robots is a weird choice of name :) ).
Hope this helps,
Your random pick works fine (even when your code is a little bit confusing). I guess your problem is, you don't understand the output of Debug.Log(robot);.
actually I don't understand what actually my output is... - OP
What does Debug.Log() print?
According to the Unity3D Documentation for this function will converted the given object to be to string representation for display. This means simply the return value of ToString() method on your Object will printed.
So let's have look at the Object.ToString() method and it's behavior in the MSDN Documentation.
Default implementations of the Object.ToString method return the fully qualified name of the object's type. - MSDN
So, your output in the Unity Log will be the Type Definition of your object.
Now, how to get useful information?
Just override the default ToString() method of your Robot class to something like this:
public class Robot
{
public string name;
public int id;
public Robot(string name, int id)
{
this.name = name;
this.id = id;
}
// Here start's the magic!
public override string ToString()
{
return string.Format("Robot -> Id:'{0}' Name:'{1}'", id, name);
}
}
I have a dictionary for clustering purpose in a class named Cluster in C# as:
Dictionary<int, List<ClusterMember>>
whereas int represent the cluster id, List<ClusterMember>> represent the members in that cluster id and ClusterMember is another class. I have shown here the whole code structure as:
public class ClusterMember
{
public string _name { get; set; }
}
public class Cluster
{
public Dictionary<int, List<ClusterMember>> _dic { get; set; }
public Cluster(int _id, List<ClusterMember> _clusMem)
{
_dic.Add(_id, _clusMem);
}
}
whereas I have used these classes in this method as:
public static List<Cluster> DP_Cluster(List<string> _customer, double _alpha)
{
var _currentClusters = 0; // current number of clusters i.e. "k"
var _memberNumber = 0; // running member number i.e. "n"
//var _dic = new Dictionary<int, List<string>>();
var _probOld = 0.0;
var _probNew = 0.0;
List<Cluster> _myClusters = new List<Cluster>();
//Cluster _cluster = new Cluster(?);
// How to Add cluster using above classes
// How to Add cluster Member using above classes
_myClusters.Add(_cluster);
//_dic.Add(_currentClusters, _customer.ElementAt(_memberNumber));
_currentClusters += 1;
for(int _i = 1; _i < _customer.Count - 1; _i++)
{
if( _i <= _currentClusters)
{
_probOld = myClusters[_i].Members.Count / ((_i+1) - 1 + _alpha);
}
else
{
_probNew = _alpha / ((_i+1) - 1 + _alpha);
}
if(_probNew > _probOld)
{
// Add _customer.ElementAt(_memberNumber+=1) to New Cluster
Cluster cluster = new Cluster( _currentClusters += 1 );
myClusters.Add(cluster);
}
else
{
// Add _customer.ElementAt(_memberNumber+=1) to Old Cluster
}
}
return myClusters;
}
Now how do I Add in _dic object of Dictionary while in for loop? Moreover I may have to add more than one cluster members to same _id more than once as
I may add a cluster member to _id = 1 in an iteration,
then have to add a cluster member to an _id = 2 in another
iteration,
then it may turn to add another cluster member to same id i.e. _id = 1 and vice versa.
Moreover, it'll be more meaningful to me if it is possible to start cluster id with 1 (not 0as of default _dic index).
Moreover I may have to add more than one cluster members to same id
more than once
You can check for the key for each loop iteration like that:
public void AddInCluster(int id, List<ClusterMember> _clusMem)
{
if (_dic.ContainsKey(id))
{
foreach (var clusterMember in _clusMem)
{
_dic[id].Add(clusterMember);
}
}
else
{
_dic.Add(id, _clusMem);
}
}
Or you can use the TryGetValue from Dictionary:
public void AddInCluster(int id, List<ClusterMember> _clusMem)
{
List<ClusterMember> members;
if (_dic.TryGetValue(id, out members))
{
foreach (var clusterMember in _clusMem)
{
members.Add(clusterMember);
}
}
else
{
_dic.Add(id, _clusMem);
}
}
Moreover, it'll be more meaningful to me if it is possible to start
cluster id with 1
What about wrapping your int into a ClusterId class which could raise exception if an id is 0?
Also your Cluster class could override the accessor operator [] on the dictionary to give a meaningful abstraction in your context (starting from 1 instead of 0 for example)
You may also add a Get working like your Add to check if this id exists:
public List<ClusterMember> GetFromCluster(ClusterId id)
{
if (_dic.ContainsKey(id))
{
return _dic[id];
}
throw new ClusterDoesNotContainsThisId(id);
}
How about using the Add method for Dictionaries? like:
if(needToAddNewCluster){
_dic.Add(index, new List<ClusterMember>());
}
if(needToExtendCluster){
_dic[index].Add(clusMem);
}
in this i assume that needToAddNewCluster checks that _dic.ContainsKey(index).
You can add method to your Cluster class
public void AddToCluster(int id, ClusterMember member)
{
// checks if cluster with specific id is already in Dictionary
if(!_dic.ContainsKey(id))
_dic.Add(id,new List<ClusterMember>());
_dic[id].Add(member);
}
You can use it in iteration like this
int id = 1; // cluster id
foreach(var m in members)
{
// adding members to cluster with id = 1
cluster.AddToCluster(id,m);
}
UPDATE
also can we get list count for each cluster id i.e. cluster members count for each cluster id?
You can add these two methods
// get members count for specific cluster id
public int GetCount(int id)
{
return _dict[id].Count;
}
// get members count for all clusters
public Dictionary<int,int> GetCounts()
{
return _dict.ToDictionary(k=>k.Key,v=>v.Value.Count);
}
Which you can access like this
var counts = cluster.GetCounts();
var c1Cnt=counts[1]; // 1 is cluster id
I would change the implementation of the Culster class slightly. The _dic should be a getter only property with an initializer. According to the usual .NET C# naming conventions, properties should be in PascalCase, therefore I renamed it to Dic. (A better name would be MemberDictionary or Members). Underlined _camelCase identifiers are usually used for fields. Method parameters and local variables have camelCase.
Then add new methods for adding one or several members. Both methods first check to see whether the list is already there. If it's there new members are added to the list, otherwise a new list is created initialized with the new members and then added to the dictionary.
public class Cluster
{
public Dictionary<int, List<ClusterMember>> Dic { get; }
= new Dictionary<int, List<ClusterMember>>();
// Initialize empty cluster.
public Cluster()
{
}
// Initialize cluster with one initial member.
public Cluster(int key, ClusterMember member)
{
Add(key, member);
}
// Initialize cluster with many members.
public Cluster(int key, IEnumerable<ClusterMember> members)
{
Add(key, members);
}
// Allows you to a one new member.
public void Add(int key, ClusterMember member)
{
if (Dic.TryGetValue(key, out var memberList)) {
memberList.Add(member);
} else {
memberList = new List<ClusterMember> { member };
Dic.Add(key, memberList);
}
}
// Allows you to add many members.
public void Add(int key, IEnumerable<ClusterMember> members)
{
if (Dic.TryGetValue(key, out var memberList)) {
memberList.AddRange(members);
} else {
memberList = new List<ClusterMember>(members);
Dic.Add(key, memberList);
}
}
}
This implementation delegates the dictionary and list creation and the details of adding members to the Cluster class.
Btw.: Dictionaries work with a key, not an index.
I don't know where you are getting the member number from, nor do I understand your clustering algorithm; however, I think that with these changes DP_Cluster could look like this:
public static List<Cluster> DP_Cluster(List<string> customers, double alpha)
{
double probOld = 0.0;
double probNew = 0.0;
var clusters = new List<Cluster>();
Cluster currentCluster = null;
for (int i = 0; i < customers.Count; i++) {
if (i <= clusters.Count) {
probOld = clusters[i].Dic.Count / (i + alpha);
} else {
probNew = alpha / (i + alpha);
}
if (probNew > probOld || currentCluster == null) {
currentCluster = new Cluster();
clusters.Add(currentCluster);
}
currentCluster.Add(_memberNumber, new ClusterMember { Name = customers[i] });
}
return clusters;
}
Some of the constructors and methods in Cluster could prove superfluous eventually, as we are always adding one single customer at a time.
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.