1

I am writing a new Betting BOT in C# for the new Betfair API and to solve some of the sins of the past BOT in which there were lots of loops and passing values to methods as parameters I am trying to split everything up as much as possible.

One method does one thing etc. I also want to define a Bet object that holds all my runner/race/bet info at the start of my "betting" job process and pass it into each method (PlaceBet, CancelBet, CheckBetStatus etc) where those values will be changed. I want to do this so at the end of the process I know all the values in my single Bet object are correct as at the moment I am using lots of variables which are getting mixed up along the way.

As I haven't done much work passing objects as reference in C# before I wanted to know the standard/best/official/fastest way of passing objects by reference.

Do I just do something like this

public struct Bet = {
   public long BetID;
   public double BetAmount;
   public int MarketID;
   public string BetStatus;
}

public BetfairBOT(){
    Bet bet = new Bet;
    // get info from DB
    bet.BetID = 10002323;
    bet.BetAmount = 10.00;
    bet.MarketID=12342;
    bet.BetStatus="";

    // get current bet status;
    this.GetBetStatus(ref bet);

   // if not matched place bet
   if(bet.BetStatus != "M"){
       this.PlaceBet(ref bet);
   }

   // save to DB
   this.SaveBet(ref bet);
  }

  private void GetBetStatus(ref Bet bet){
   // do some stuff
   bet.BetStatus = "U";
   return;
  }

or should I use the Bet object as the return type of the method and return it each time e.g

// get current bet status; Setting the bet object to the return object which is passed in by reference
bet = this.GetBetStatus(ref bet);

private Bet GetBetStatus(ref Bet bet){
    // do some stuff
    bet.BetStatus = "U";
    // return my changed object
    return bet;
}

Or should I do it some other way?

Also should I use the "out" parameter instead of "ref"?

I just want to know the "accepted" "best practise" way of passing objects in by reference and returning them so that I don't lose any data along the way.

By the way is there not a better way to format the code in this editor? I have tried indenting some of the ending brackets but they just don't want to be part of the code block above them.

Are there [code] tags I could use instead?

Thanks for any help in advance.

Rob

Luaan
  • 62,244
  • 7
  • 97
  • 116
MonkeyMagix
  • 677
  • 2
  • 10
  • 30
  • 1
    Well, looking at your code, perhaps you want to use `class` rather than `struct`. Then you no longer have to use `ref`, because classes are "always" passed by reference. – Luaan Feb 14 '14 at 13:38
  • possible duplicate of [When to use ref vs out](http://stackoverflow.com/questions/1516876/when-to-use-ref-vs-out) – ken2k Feb 14 '14 at 13:45
  • @Luaan - Classes are not always passed by reference. Unless the ref (or out) keywords are used, the default passing mechanism is by value. When a reference _type_ is passed _by value_ a copy of the reference is passed. – Chris Dunaway Feb 14 '14 at 17:33
  • @ChrisDunaway Right, let's ignore that that's not how the OP uses the `ref` :) Classes are passed by reference. Whether their reference is passed by reference is a completely different question :) – Luaan Feb 14 '14 at 20:16

3 Answers3

4

Unless you really need to (and know what you are doing), don't use structs. Use classes whereever possible. Your life will be easier and will work 'automatically' most of the time.

Ondrej Tucny
  • 27,626
  • 6
  • 70
  • 90
3
  1. Don't use a struct, use a class for your bet object. Structs are value types and should therefore be immutable, but you are passing it around and changing the internal values.

  2. For what you wish to accomplish, you don't have to "pass by reference". Objects are already sort-of passed by reference. Remember that objects are reference types already. When you create an object, it is somewhere in memory and the variable holds the memory address of that object. When you pass it into a method, the memory address does get copied into a new variable since C# is pass-by-value, but the variable points to the same object.

You're not actually passing the object around, you are only passing a reference to that object around.

dursk
  • 4,435
  • 2
  • 19
  • 30
  • Ok, cheers. So I should swap my Bet struct for a Bet class and then instantiate that with the values from my DB recordset (the DB, picks the bets and provides my Service a recordset of Bets that need to be placed/cancelled etc) I just want the Windows Service I am writing to be a dumb terminal that receives the data from the DB (as that does all the work analysing the races/runners and deciding which bets to place) and then acts on the command (place/cancel bet etc) before updating the DB with the result. So passing objects to my methods and changing the values doesn't need any special params? – MonkeyMagix Feb 14 '14 at 15:49
  • Exactly. The thing to keep in mind is that when you say `Bet myBet = new Bet()` a `Bet` object gets created somewhere in memory and `myBet` holds a reference to this memory location. So when you pass `myBet` to a method, all you are passing is the reference to the `Bet` object. – dursk Feb 14 '14 at 16:03
0

You are having this problem because you are defining Bet as a struct. If you are storing Bets in the Database with a primary key it should usually be a class instead. (ValueObject vs Entity)

Once it's a class you no longer have to do all the "by ref" passing. Check this question for when to use a struct. My rule of thumb: Don't ever use structs unless you have very good reasons to do so.

Not really related to your question but:

Avoid magic strings: bet.BetStatus = "U";. You can either use constants, or (better) an enum to get rid of the magic strings. Or you can make the enum private and use methods like 'Bet.HasEnded() which would equal Bet.Status == 'E'.

Open/Closed Principle: // get info from DB. You will probably get a better design by passing a Bet to the constructor or by using a factory. With the current code you are binding your BetfairBOT with your database which will make automated testing more difficult.

Community
  • 1
  • 1
Laoujin
  • 9,962
  • 7
  • 42
  • 69
  • It was just a basic example to show you what I meant. I have separate classes for all my objects and API code etc. This was just an example to show you that I was populating the Bet object with values from a DB without having to write the code out. The bet statuses are fixed string values from betfair M = Matched, S = Settled, U = unmatched, L = Lapsed, C = Cancelled etc. I could change them to an Enum but what benefit would I get from that if the values are never going to change? – MonkeyMagix Feb 14 '14 at 15:45
  • ok, good article. As my current struct holds information (currently) to 2 other structs BetSelectionPrice (which has BackPrice, LayPrice) and MarketInfo (which has MarketID, MarketType, MarketStatus) should I use classes for these as well even though in one instance of my Bet objects life (one call to the RunJob method) a Bet object will hold a MarketInfo object and a BetSelectionPrice object with values that WON'T change. E.G the prices, marketID, marketStatus won't change in one call. So should they be structs or objects. They are small and the values won't change. – MonkeyMagix Feb 14 '14 at 15:55
  • `I could change them to an Enum but what benefit would I get from that if the values are never going to change?` : **Readability**. Right now you know M=Matched but if someone else joins the team or after having the source laying around for 6 months, chances are you no longer know what M means **exactly**. When it's an enum (or constant) you can also provide an XML comment to tell the dev working with your source some details about that status. What does "Matched" mean, what is the status before, what is the most likely status after etc. – Laoujin Feb 17 '14 at 09:54
  • Why would you want to use a struct for `MarketInfo`? What do you hope to gain? MarketInfo is not a [ValueObject](http://martinfowler.com/bliki/ValueObject.html) because it has an ID but even if there is no ID, that doesn't force you to use a struct. You can perfectly design value objects as classes. If you are unsure whether you should use a class or struct: Go for a class. If you think you would gain a performance gain, make sure you measure it. If you end up with your struct being passed by reference all the time, the only thing your struct gained was additional `ref` typing :) – Laoujin Feb 17 '14 at 10:02
  • Hi re using Enums for M=Matched, S=Settled etc. From what I read the underlying value for an enum cannot be a string. So how would I define the enum CurrentBetStatus = {None="",Matched="M",Settled="S",Cancelled="C",Voided="V"} etc as the values need to go into the DB as M,S,C,V etc and they will come back out again as M,S,C,V. From what I can see you cannot define an enum as a string but from what you are saying that is what I need to do. What is the best approach for mapping an enum to a string like this. Remember my DB is already using the standard values (M,S..) to find Matched/Settled bets – MonkeyMagix Feb 17 '14 at 18:02
  • You could create functions like IsMatched(), IsSettled(), etc. When using this approach, it no longer matters how it is stored in the DB, the string constants become implementation details (private field & constants) with the added benefit that when the check for Settled changes from `Status=='S'` to `Status=='S' && Items.Any()`, you'll have to do this change in one location only compared to scattered all over the application(s). – Laoujin Feb 18 '14 at 12:56
  • If you use an ORM framework, you can create [a custom mapper](http://stackoverflow.com/a/4639558/540352) that converts the strings to your enum (or something else) whenever you fetch an entity from the DB. – Laoujin Feb 18 '14 at 12:57
  • Eric Lippert also touches [struct vs classes in this talk](http://softwareintegrity.coverity.com/top-5-things-every-csharp-dev-needs-to-know.html) – Laoujin Feb 18 '14 at 13:00