views:

468

answers:

7

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. . .

+6  A: 

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.

Daniel Earwicker
Using a lambda for Sort means you will have LINQ support, in which case the OrderBy syntax is (imo) easier to use.
Thorarin
True, but for large data sets, `Sort` on `List` may be a bit faster - depends which is more important to you.
Daniel Earwicker
A: 

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.

DanDan
What do you mean "loose typing"?
Tamás Szelei
Probably means dynamic or runtime typing. C# has strong support for static (compiletime) typed, meaning that you tell the compiler (or it figures out) the types of object stored in variables, allowing it to optimise and find many simple errors.
Daniel Earwicker
Earwicker is correct, loose or weak typing is the opposite of strong typing: http://en.wikipedia.org/wiki/Weak_typing
DanDan
+2  A: 
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>.

John Fisher
A: 

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.

Tamás Szelei
I'd just like to add that instead of a base class, you could use an interface. Especially important because multiple inheritance is not supported in C#.
Thorarin
+2  A: 

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 );
LBushkin
A: 

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

chris166
A: 

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);
}
Joel Coehoorn