I have a List that is full of objects from another class than where I am trying to grab the variables.
I thought I could use a foreach loop and go through the list of objects then grab the variables like i normally would but i only am getting the methods from the class I'm trying to pull from
public void fillArray()
{
foreach(Assignment1.Post p in Assignment1.allPosts)
{
postTitle = p.PostTitle;
postID = p.PostID;
postContent = p.PostContent;
postScore = p.Score;
date = p.TimeStamp;
DisplayObjects newObj = new DisplayObjects(postTitle, postID,postContent,postScore,date,timeStamp);
postObjects.Add(newObj);
}
sortList();
}
here is the object declaration and here is where i am trying to access it in another class:
foreach (DisplayObjects d in DisplayObjects.sortedPosts)
{
// d.VariablesIWantToAccessButCant
}
Probably something extremely basic but I just am missing the core concept. Thanks for the help as always
All of my variables being placed into the objects were private so I was not able to access them since I had no get or set methods. Very dumb but I figured it out
Related
First of all I will say that I've changed my design and no longer need that but getting a good answer for that will still be nice
I have the following class, ListContainer, in my code (The attached codes are all mcve):
class ListContainer
{
public object ContainedList
{
get; private set;
}
public int Value
{
get; private set;
}
public ListContainer(object list, int value)
{
ContainedList = list;
Value = value;
}
}
And in some other class in my code I have a List<ListContainer> and I need each ListContainer to contain this List<ListContainer>, so I can implement it like that:
//Field in the class
List<ListContainer> mContainers = null;
//In the constructor:
mContainers = new List<ListContainer>();
mContainers.Add(new ListContainer(mContainers, SOME_CONST));
mContainers.Add(new ListContainer(mContainers, SOME_OTHER_CONST));
Than it works fine, but when I've tried to use list initializer:
//Field in the class
List<ListContainer> mContainers = null;
//In the constructor:
mContainers = new List<ListContainer>
{
new ListContainer(mContainers, SOME_CONST),
new ListContainer(mContainers, SOME_OTHER_CONST)
}
You would expect the results to be equivalent but in reality the result looks like that:
mContainers
[0] - ListContainer
ContainedList = null
Value = SOME_CONST
[1] - ListContainer
ContainedList = null
Value = SOME_OTHER_CONST
Seeing this results I've inspected the output MSIL of this C# compilation and seen the following code:
Now, this explains why the problem occurs, and I've even checked out in the CSharp Language Specification document and this is the defined behavior:
A List can be created and initialized as follows:
var contacts = new List<Contact> {
new Contact {
Name = "Chris Smith",
PhoneNumbers = { "206-555-0101", "425-882-8080" }
},
new Contact {
Name = "Bob Harris",
PhoneNumbers = { "650-555-0199" }
}
};
which has the same effect as
var __clist = new List<Contact>();
Contact __c1 = new Contact();
__c1.Name = "Chris Smith";
__c1.PhoneNumbers.Add("206-555-0101");
__c1.PhoneNumbers.Add("425-882-8080");
__clist.Add(__c1);
Contact __c2 = new Contact();
__c2.Name = "Bob Harris";
__c2.PhoneNumbers.Add("650-555-0199");
__clist.Add(__c2);
var contacts = __clist;
where __clist, __c1 and __c2 are temporary variables that are otherwise invisible and inaccessible.
So obviously this behaviour is intended. Is there a good reason everything is done on the temporary variable and not on the original one? since it seems like a wrong behaviour to me.
The reason is to avoid race conditions with concurrent threads accessing the original variable where you would add your elements. An inconsistency would appear if a thread accesses the variable while not all elements are added to it yet.
Two threads accessing the same variable would therefore get an inconsistent list, with different elements in it.
This would not come as a shock if the elements are added on different lines, but since you use an object initializer, it is normal to perceive the object as directly initialized with all its elements in it, hence the need of a temporary, invisible, variable.
Is there a good reason everything is done on the temporary List and not on the original one?
There is no original list:
var __clist = new List<Contact>();
// …
__clist.Add(__c1);
// …
__clist.Add(__c2);
var contacts = __clist;
Only one list is ever created. What you probably mean is that it’s done on a temporary variable instead of the original variable, but that has no practical effect—other than probably being easier to implement. This is especially true if you think about that collection initialization is not limited to the context of variable assignments:
SomeMethodCall(new List<int>() { 1, 2, 3 });
Since there is no reference to that list, the simplest solution to implement this is just to use a temporary variable that holds the list, and put that variable at the place of the initializer then.
What’s also important about this is that the old value is completely overwritten. So in your mContainers = new List<ListContainer>, the old value of mContainers is never being looked at for the purpose of the initializer syntax.
It’s probably a good idea to think about the collection initialization as an “atomic” operation. The list only exists (at least to you) once the whole initializer completes. So you cannot reference itself from within the initializer.
Assignments are first evaluated on the right side of the = and then the assignment takes place. So mContainers is still null.
I'm trying to store information in a block of anonymous values
//holds all info
var jobs = new { newJob, numBytes, requiredTime };
then take that information and place it into a list as a single element
//puts above info into a list
joblist.Add(Convert.ToString(jobs));
Console.WriteLine(joblist[0]); //testing purposes
now what I would like to do is be able to call joblist and take the value of example numBytes at position 4.
Is this possible? Or could someone help with an alternate way of doing this? Much thanks!
Create a named class. Then you can have a list of objects of that type and manipulate that list in any way you want.
Using classes is best-practice for what you are trying to do. By default you should consider storing structured data in an object model consisting of custom classes. There is another answer here which is proposing to use dynamic - this is valid and has its place, but it is more of a last resort solution. What you want is to play to the strength of C# which are rich classes and static typing. Anonymous types are also statically typed, but as you cannot name the type you cannot declare a statically typed list to hold them. You also can't use them as return types of methods.
The "normal" thing to do in C# would be to create a class to hold the information that you want to store. For example:
public class Job
{
public string Name { get; set; }
public int NumBytes { get; set; }
public DateTime RequiredTime { get; set; }
}
Then you can add these to a list:
var jobs = new List<Job>();
var aJob = new Job();
aJob.Name = "Job 1";
aJob.NumBytes = 123;
jobs.add(aJob);
Then you can access jobs by its index in the list:
var jobNumBytes = jobs[3].NumBytes;
One thing to note about C#, when you do:
new { newJob, numBytes, requiredTime };
The compiler, at build time, just creates you a strongly typed class (just like the Job class I created above) and generates a random name for it. It infers the property names and types from the variables that you are assigning to it. The created .exe or .dll actually does contain a class definition for this type, you just can't easily get to it from other places in your code. It isn't truly "dynamic". So using that syntax is usually just a lazy way of declaring a class that you just need for a moment. Usually just inside 1 method, then you don't need it any more. Creating a named class is usually what you want to do.
Actually I don't know exactly what you mean with "now what I would like to do is be able to call joblist and remove for example numBytes at position 4."
But I guess you just want to put the objects in a list and query for numBytes and maybe remove some elements.
With dynamics you can handle dynamic objects...
var jobs = new List<dynamic>();
for (int i = 0; i < 100; i++)
{
string newJob = "Job" + i;
int numBytes = i;
TimeSpan requiredTime = new TimeSpan(0,0,i);
//holds all info
var job = new { newJob, numBytes, requiredTime };
jobs.Add(job);
}
jobs.RemoveAll(p => p.numBytes > 50);
Instead of this, I agree with the comments below your question and would create a normal class which holds the properties you need and simply put instances of that into a list. Dynamics should be used only in very rare situations, and yours doesn't sound like it is extremely special.
I have a large amount of nested foreach loops and I'm running out of variable names to use...
Could I do something like this :
//int i = 1
string "number"+i = new String("FirstElement");
I've seen some posts about this for languages such as C and javascript, but I don't know how to do it in C#.
In case you can't name variables after other variables : how could this problem otherwise be solved?
This problem could otherwise be solved by using meaningful variable names - running out of names would mean running out of concepts for what the thing is trying to achieve, which is hard to believe.
If your requirement is to work with a collection of variables, then put them in a collection; if it's to have n number of variables all strictly defined by name, then name them explicitly, and so on.
var a = new List<int>();
for(int i=0;i<100;i++)
{
a.Add(i);
}
Console.WriteLine(a[0]);
Console.WriteLine(a[1]);
etc....
This way you make list which contains 100 elements, you can access them by nameoflist[index]
A while back I asked a similar question:
Python - neat way of creating multiple objects?
Basically, if you have lots of very similar variables named things like variable_1, variable_2, etc, then thats normally a sign that you should be using an array or list of variables instead.
So instead of 10 separate string variables, create a list (or array) of strings.
The way you are doing will not work in C#. You can not create variables at run time. If you want
you have to use a list to store your variable name and value. Therefore you better create a class to hold name of the variable and value.
class Variable
{
string Name;
string Value;
}
Now create another class to hold variables
class VaraibleHolder
{
List<Variable> Variables;
VariableHolder()
{
Variables = new List<Variables>();
}
public void Add(Variable Vbl)
{
Variable vbl = Variables.SingleOrDefault(v=>v.Name == Vbl.Name);
if(vbl == null)
{
Variables.Add(vbl);
}
}
public void Remove(string VblName)
{
//this is a lamda expression.
Variable vbl = Variables.SingleOrDefault(v=>v.Name == VblName);
if(vbl != null)
{
Variables.Remove(vbl);
}
}
public Variable GetVariable(string VblName)
{
Variable vbl = Variables.SingleOrDefault(v=>v.Name == VblName);
return vbl;
}
}
So you can use Variable holder to create and store varaibles at runtime. Hope this will help you.
I'm very new with c#, and was previously attempting to ignore classes and build my small program structurally more similar to PHP. After reaching a road block, I'm trying to start over and approach the problem properly OO. I'm taking a long file, and in a loop, every time certain conditions are met, I want to make a new object. How can I have it create a new object, without having to specify a unique name?
Referral ObjectName = new Referral(string, string, int);
Secondly, once this is done, and the strings & int set their appropriate object properties, how can i unique-ify the class by one property, and then sort the class by another?
I'm sorry if these are basic questions, I have spent a large, large amount of time first trying to figure it out on my own with google, and a textbook. If only C# would allow multi-dimensional arrays with different types!
Thank you so much!
PS. I do mean to extract a list of unique objects.
All these answers, while helpful, seem to involve creating a shadow set of IEnumerables. Is there no way to do this with the class itself?
Trying the first solution, provided by Earwicker, adding each object to a List from within the loop, when I try to Write a property of the element to the console, i get the ClassName+Referral. What could I be doing wrong?--solved. still needed .property
still working. . .
C# does allow untyped arrays. All objects are derived ultimately from object, so you use an array or container of objects. But it's rarely necessary. How many types of object do you have?
Within the loop block, you can create an object exactly as you do in that line of code (except with the syntax fixed), and it will be a new object each time around the loop. To keep all the objects available outside the loop, you would add it to a container:
List<Referral> referrals = new List<Referral>();
// in the loop:
Referral r = new Referral(str1, str2, num1);
referrals.Add(r);
Suppose Referral has a numeric property called Cost.
referrals.Sort((l, r) => l.Cost - r.Cost);
That sorts by the cost.
For ensuring uniqueness by some key, you may find it easier to pick a more suitable container.
Dictionary<string, Referral> referrals = new List<Referral>();
// in the loop:
Referral r = new Referral(str1, str2, num1);
referrals[str1] = r;
This stores the referral in a "slot" named after the value of str1. Duplicates will overwrite each other silently.
First, you're going to need to spend some time familiarizing yourself with the basics of the language to be productive. I recommend you take a little time to read up on C# before getting in too deep - otherwise you'll spend a lot of your time spinning your wheels - or reinventing them :)
But here's some info to get you started.
Typically, in C# you create classes to represent elements of your program - including those that are used to represent information (data) that your program intends to manipulate. You should really consider using one, as it will make data manipulation clearer and more manageable. I would advise avoiding untyped, multi-dimensions array structures as some may suggest, as these rapidly become very difficult to work with.
You can easily create a Referall class in C# using automatic properties and a simple constructor:
public class Referall
{
// these should be named in line with what they represent...
public string FirstString { get; set; }
public string AnotherString { get; set; }
public int SomeValue { get; set; }
public Referall( string first, string another, int value )
{
FirstString = first;
AnotherString = another;
SomeValue = value;
}
}
You can add these to a dictionary as you create them - the dictionary can be keyed by which ever property is unique. Dictionaries allow you to store objects based on a unique key:
Dictionary<string,Referall> dict = new Dictionary<string,Referall>();
As you process items, you can add them to the dictionary:
Referall ref = new Referall( v1, v2, v3 );
// add to the dictionary, keying on FirstString...
dict.Add( ref.FirstString, ref );
If you need to sort items in the dictionary when you're done, you can use LINQ in C# 3.0:
IEnumerable<Referall> sortedResults =
dict.Values.OrderBy( x => x.AnotherString );
You can sort by multiple dimension using ThenBy() as well:
IEnumerable<Referall> sortedResults =
dict.Values.OrderBy( x => x.AnotherString )
.ThenBy( x => x.SomeValue );
List<Referral> referrals = new List<Referral>();
for (...)
{
referrals.Add(new Referral(string1, string2, number1));
}
Then, if you're using Linq (which I highly suggest), you can do this:
IEnumerable<Referral> sorted = referrals.OrderBy(x => x.string1).ThenBy(x => x.string2);
Otherwise, you can use the Sort() method on List<Referral>.
You can create an object without a reference, but you won't have any access to it later:
new Referral(string, string, int);
If you wish to put them in an array/list, these different types need to have a common base class. This is called polimorfism, which is a very important concept in OO programming.
You cannot ignore classes while using c#. Don't resist the change!
Do you really not need to create a class here? Do you really not need to give it a name? C# does allow loose typing, but type safety is a good thing.
I don't fully understand what you're trying to do. But maybe LINQ is what you're looking for. There's tons of documentation around, but as a quick 'teaser' have a look at the 101 Linq samples on MSDN
C# includes a wonderful feature called "iterator blocks". What you want to do is use the yield keyword to create an Enumerable of your Referal object, something like this (not that I'm making the file format and property names up, because you didn't share that):
public class Referral
{
public Guid id { get; private set; } // "uniquify"
public int ReferringId { get; set; }
public string ReferrerText { get; set; }
public string ReferrerDescription { get; set; }
private Referral()
{
id = new Guid();
}
private Referral(string Text, string Description, int ReferringId) : this()
{
this.ReferrerText = Text;
this.ReferrerDescription = Description;
this.ReferringId = ReferringId;
}
public static IEnumerable<Referral> GetReferrals(string fileName)
{
using (var rdr = new StreamReader(fileName))
{
var next = new Referrer();
int state = 0;
string line;
while ( (line = rdr.ReadLine() ) != null)
{
switch (state)
{
case 0:
next.ReferrerText = line;
state = 1;
break;
case 1:
next.ReferrerDescription = line;
state = 2;
break;
case 2:
next.ReferringId = int.Parse(line);
yield return next;
next = new Referral();
state = 0;
break;
}
}
}
}
}
Now you want to sort the referrals and presumable enumerate over them for some purpose. You can do that easily like this:
foreach (var referral in Referral.GetReferrals(#"C:\referralfile.txt").OrderBy( r => r.Text ) )
{
OutputReferral(referral);
}
I use this type of construct often.
response = new LocationResponse ();
response.LocationDetails = new LocationDetail[4];
response.LocationDetails[0] = new LocationDetail();
response.LocationDetails[0].site = "ABCDE";
...
The piece I don't fully understand is this piece:
response.LocationDetails[0] = new LocationDetail();
Why does each individual element of the array have to be instantiated?
If you leave it out, you get undefined exceptions.
Well if an array elements were automatically instantiated, you would be locked into which classes you defined the array with. You wouldn't be able to use arrays of abstract classes or interfaces or any object which doesn't have a default constructor. This is just naming a few problems with automatically instantiating objects in an array.
You don't need to instantiate LocationDetail if it is a value type (struct). You have to instantiate it if it's a class because the default value for a reference type is null.
This code works:
public struct LocationDetail
{
private string site;
public string Site
{
get { return site; }
set { site = value; }
}
}
static void Main(string[] args)
{
LocationResponse response = new LocationResponse();
response.LocationDetails = new LocationDetail[4];
response.LocationDetails[0].Site = "ABCDE";
Console.Write(response.LocationDetails[0].Site);
}
Think of it as a reference pointer, if you don't initialize you have a null value on each of the LocationDetail items.
It set each element to null, which is the default value for a class until you say otherwise.
How can C# automatically instantiate the elements for you? Perhaps that type in your array doesn't even have a default constructor. Maybe you don't want to consume the memory required by an entire array of elements before you actually have them.
I don't see the advantage to having the runtime try to fill that array in advance.
I think of arrays as egg-cartons. You can declare an egg carton, but that doesn't put eggs in your carton - you still have to decide what kind of egg to put in each slot of the carton. You might want easter eggs in some, but grade AA free-roam brown eggs in others.
The array itself can't know what you want ahead of time, so it defaults to putting nothing in your slots.
It would be a costly operation, depending on what needs to be done to create the objects. Furthermore, what if the objects cannot simply be instantiated? Or if you need an array of a given type, where only some fields will eventually contain an object and others shoud be null?
As others have pointed out, the array will be full of nulls after you declare it. You can simplify your initialization logic somewhat by doing this:
response.LocationDetails = new LocationDetails [] {
new LocationDetails(),
new LocationDetails(),
new LocationDetails(),
new LocationDetails()
};
And what would be even nicer is if the LocationDetails constructor had an overload that took a siteid:
response.LocationDetails = new LocationDetails [] {
new LocationDetails("ABCDE"),
new LocationDetails("FGHIJ"),
new LocationDetails("KLMNO"),
new LocationDetails("PQRST")
};
Or the super fancy C# 3.0 stuff that Justice points out :)
response = new LocationResponse() {
LocationDetails = new LocationDetail[] {
new LocationDetail { site = "ABCDE" }
}
}