I've been studying C# for a couple of years, reading voraciously, even taking a few C# data access courses from Microsoft. I've also been reading books on OOP. I'm coding a web-based database application at work. While my job title is not "programmer", I'm fortunate enough to be able to work on this as a side project. I coded in Basic in the early 80's and was even good at utilizing pokes and peeks to manipulate the Apple ][ + and the TRS-80 to astound and amaze my friends. But that was a very linear approach to coding.

All this being said, something is just not clicking with me. I haven't had that a-ha moment with either C# or OOP that gives me the ability to sit down, open up VS2008, and start coding. I have to study other people's code so much that it simply seems like I'm not doing anything on my own. I'm getting discouraged.

It's not like I'm not capable of it. I picked up t-sql really quickly. Someone can tell me what information they want out of the database and I can code out the tsql in a matter of a few minutes to give them what they want. SQL is something that I get. This isn't happening for me with OOP or C#. Granted, C# is inherently more complex, but at some point it has to click. Right?

I read over stackoverflow and I'm overwhelmed at how infinitely smart you all are.

What was it for you that made it click?

Edited to add: A lot of the answers here were outstanding. However, one in particular seemed to have risen to the top and that's the one I marked as the "answer". I also hate not marking my questions with the answer.

+3  A: 
  1. First Step for me: Understanding FOR loops in Turbo Pascal 5. That forever changed my life.
  2. Second Step: Understand, that every object is kind-of like a button (or any other ui control), just usually invisible.

You might be interested in reading this:

Coding Horror: Separating Programming Sheep from Non-Programming Goats

A button? How do you mean? The only interpretation I can think of is frighteningly incorrect.
I knew a button is a thing with Properties (Name, Caption, Left, etc..), Events (OnClick, OnMouseMover etc), Methods (Click). It was easy to understand cause the button was something you could see and work with. Then I understood all objects are like that.
+2  A: 

I remember this feeling. I was contracted to work on an application in ASP.NET and C#. Problem is, I wasn't a C# developer, and the Employer knew it! But because I had previous programming experience with them, they encouraged me to give it a shot. I was a PHP developer, stepping into a .NET world.

The first week was frustrating. I remember getting angry asking why I can't just include("sideNavigation.php") to get my navigation on the page. Instead I have to make some control, add it to some other control - it didn't make any sense. But I kept reading.

ASP.NET started catching on, and the markup was making a lot of sense. As I learned the markup aspect, I started becoming a bit more familiar in the code-behind. I knew what properties and methods existed for more things, and what types of values they accepted.

Of course places like www.learnvisualstudio.net came in handy too, with video-tutorials on C# and VB.NET.

Today I'm still a PHP Developer, but I feel comfortable enough with .NET that I could get back into VS2008 and tinker around until I get my solution(s).

All things with time, my friend. Another helpful thing is to find a .NET user-group and visit regularly.

Jonathan Sampson
See that's just it. I bought a lifetime membership to learnvisualstudio.net and I feel as if I have to watch a video for every little thing I'm trying to code. Grrr...
Is it me, or are these video tutorials really annoying. I'd rather just read the damn thing at my own pace without audio.
Andrew Rollings
@Andrew - Some people enjoy reading, some watching. I have numerous thankful visitors to www.sampsonvideos.com
Jonathan Sampson
@Gregd - I agree. It feels that way at times. Just create small projects for yourself, and take notes on your development along the way. Find a local .NET group, and visit regularly.
Jonathan Sampson
@Jonathan Sampson : sneaky plug :) I'll take a look. Maybe I'll change my mind... Tell me, do you have subtitles for us 'no audio/hard of hearing' people?
Andrew Rollings
@Andrew - No, unfortunately I don't. I should, especially being as conscious about accessibility as I am. I apologize.
Jonathan Sampson
+3  A: 

There is no real advice I can give you, because you are completely right : it has to click. OOP is hard to explain so everyone gets it, just like one may have a hard time understanding windows messages, foreign primary keys, and just about every other topic worth mentioning.

What I would suggest is that you try to do a real project on your own. It doesn't have to be complex, but it has to include several classes, so you can get your hands dirty with inheritance and other sweet OOP stuff.

I don't think that any amount of reading can ever replace your own experience ... Until it does click just pretend you're playing Alone in the Dark or something ...

+25  A: 

Learning about interfaces did it for me. Coming from a scripting background and switching to OO, I didn't see how creating all these classes was any more efficient. Then I read Head First Design Patterns, and suddenly I saw the why. It's not the most detailed book, but it's a fantastic first step to explaining the "why" of OO programming, something that I struggled with immensely.

Hope this helps.

Mike Robinson
This is helpful because it points to a specific instance when it clicked with you. Thanks for that
+1 for the Head First books, the really approach explaining hard topics in a totally different way than ordinary CS textbooks.
Peter Lindholm
I have the exact same story. Before reading Head First Design Patterns, I understood some of the mechanics of OO, but I couldn't figure out what it was actually good for.
+1 for Head First Design Patterns; that book really helped me understand OO concepts
Andreas Grech
+1  A: 

The first steps into any language should be the "Hello World" tutorial. The magic behind this method of learning, also called learning by doing, is the fact that it puts a immediate necessity as the main learning motivator. I am myself a C#.NET developer, and I am currently struggling to learn F#. The steps I should take after writing my HelloWorldApp is set small and easy goals like

Write an console application that downloads some page on the net and display its HTML content.
Do it again, but now asynchronously.
Do it again, but now multiple pages in parallel.


That's how I learn something. For OOP the things get a bit more complicated, you should read other people's code and articles too. One thing that helps you to lear OOP and refactoring by yourself is reusing your own code. In my example above, you'll note that the code written to download a page synchronously is very similar to the one used to do it asynchronously, they have even some lines that are 100% equal. What you should do to learn OOP is refactor and encapsulate your code, so you can choose wether type of download do you want (sync or async) with the minimum repetition in the code written for both options. If you use TDD (Test Driven Development) the learning curve will improve.

Jader Dias
+1  A: 

Dunno... For me, it was Turbo Pascal 6 that introduced the concept of OOP but I didn't quite get it back then. Then I've learnt C++ and everything immediately became crystal clear. Coming from C++, C# is just seems really straightforward so I couldn't really say that I had an a-ha moment with C# or .NET.

I guess you just have to write code. Lots of code.

+1  A: 

I think the only way to truly understand any new technology is to work with it day in and day out. Sure, you can learn lots of new things at a high level without getting too deep, but to get that "ah ha" moment, to really grok the language and patterns, you have to invest a lot of time into just doing it.

Sadly, that means your main line of work really has to be programming in C#. If you are just doing it here and there as a series of side projects, it's gonna be frustrating and slow going.

Just my opinion based on my own experience...

+20  A: 

The majority of posters on SO are not exceptionally intelligent. There are a couple things that may skew you to think that is the case. First, only people who happen to know or think they know an answer will bother to respond. Second, incorrect/bad questions and answers are not visible. Third, it's natural that collective knowledge will be much greater than individual knowledge.

The thing that you mistake for intelligence, is time spent in an arena. The more time and effort you devote to learning the better and more knowledgeable you will become. From what you are saying, you are not approaching things in an optimal way. Understand that a specific language just provides the rules of syntax and grammar. The key to becoming a good developer is to be being a good thinker. Don't focus or get hung up on a language.

Craig Larman and Bruce Eckols and the Head Start books are a great fit for this model of learning. However, I do have to warn you that reading the books and doing the exercises is not enough. You've got to immerse yourself in discussion and feedback with other developers (unless of course, you are an exceptionally intelligent person - in which case you'll simply get it...).

You've demonstrated a trait that is more important than intelligence. You've got humility. If you have humility and perseverence, you'll be much more effective and knowledgeable than the vast majority of the posters on SO.

Humility is also important because it will help you cope with the fact that no matter how hard you work and how much you study, you'll never know more than Jon Skeet.

Ha. An insightful, intelligent and humorous post. Thanks for that!
Great answer, +1 !
Dimitre Novatchev
*Bruce Eckels. *Head First books.
You can know more than Jon Skeet. Ask him if you don't believe me. However, it will **NOT** be easy.
Andrei Rinea
AMEN! Love the power and intelligence of the masses when it is focused on a "good" purpose. Also agree that humility and perseverance are very important.
Mike Grace
+3  A: 

I'm not sure whereabouts you are within your C# journey, but I certainly found Head First C# a very good read and use the mini projects therein as practice. As someone who had been studying C# in their spare time for around a year and a half prior to reading the book, it gave me some mini 'Aha' moments, for example, with delegates and callbacks.

Granted, some of the examples within it are contrived, much like many other programming books, but hey, who doesn't want to build their own Space Invaders?!

Russ Cam
I bought Head First OOAD, which I'm currently reading, and Design Patterns. I haven't picked up the C# one, but maybe I will now. Thanks.
Try and pick up the September 2008 edition if you can, as a lot of earlier errata were corrected in this version.
Russ Cam
I'll check safari online..
Somebody in the Head First forums wrote an errata parser for all editions. Can be found here - http://www.headfirstlabs.com/phpBB2/viewtopic.php?t=6571
Russ Cam
+1  A: 

i felt the same way learning c# and oo. I would understand the principles, but not know what to do with them practically. I used to program Fortran so whenever i get lazy I rely on brute force. Ive noticed lately that while I am still missing something,a lot of it is starting to come together. Despite all reading, the most effective way for me has been to simply write a small program or small task and while im doing it think of all the alternative ways i could be doing it. THat forced me to ask questions and look up answers. It takes a lot of time, but i have had more and more "ah ha" moments. I dont think there is a final "ah ha". you just get more comfident manipulating the code.

OO tries to replicate a natural thinking, but in my opinion, it is a not valid.

I have wondered if perhaps I should move to something non oo like LISP, but resources seem few.

I tend to agree with you on OOP. It's supposed to make things easier. Really?
I will say, that by yielding to oo a bit, i have become more organized with my thoughts, but not necessarily more effective.
+2  A: 

I agree with Jeremy McCollum. Maybe you need to stop reading and start doing!

Ok, don't really stop reading, but at some point, the only way to become a better programmer is to actually work with the tool/language you are trying to learn.

My scenario is a lot like yours. While my day job is programmer, it's not C# or even .Net. The way I got the coin to drop was to actually start working on a real project. It's not even a big project, but it's a real project where I had to learn how to do a number of things I had never done (in C#).

Do exactly what you said you can't: sit down, open up VS2008, and start coding. Just do it!

Approach it like a real job, no easy outs! Pretend your employment depends on it. For me, it actually does, since I do want to get a C# job at some point in the future. If I can't complete projects, that will never happen.

Actually I AM doing it! Part of the issue is that while I can drag and drop stuff in VS and make it work, it's not clicking for me, WHY it's working. It also isn't helping to learn OOP concepts.
+7  A: 

Write code. Lots of it. Bad code, good code, useless code - it doesn't matter. Just write it. When you're sick of writing code (and if you're not getting sick of it occasionally, you're not writing enough) read blogs, magazines, and books about code.

Then, go back and look at some of your previously written code. Refactor it, clean it up, and change the design. Add features, fix bugs, whatever - doesn't matter. Delete your existing code, and write more code.

At some point, you'll begin to think in C# - just like you do in SQL.

Note that this is similar to learning a foreign language by immersing yourself in it. Sure, you can study it in school, read a book, and listen to tapes. But, there's no better way to learn a foreign language than to moving where it's spoken every day.

Mark Brackett
+2  A: 

I can totally sympathize. I have degrees in English and Film; the only programming I'd done before my latter twenties was on an Apply ][e, when I was 12. Classic ASP was my first foray into Web programming, which I only learned because I had to, as a technical writer working on an intranet project documenting real-estate software.

But eventually programming took, and I decided to start learning how to do things right. The transition wasn't easy. But I can say learning C# for Web development, particularly if you don't already sort of "grok" OO, can be daunting -- mainly because OO is so much about creating and managing state and statefulness, and the Web is inherently stateless.

Believe it or not, I learned more about OO writing Ajax apps with JavaScript and Flex apps in ActionScript -- i.e., building stateful clients -- than I ever did trying to force C# into my brain, because Ajax apps and Flex apps force you to think about things in terms of state. Returning to C# after having spent a couple of years (yes, a couple of years) writing lots of JavaScript code, and lots of Flex code, and reading lots and lots of both, was actually pretty easy, because by then, I realized how C# should work, as an OO language.

The Head First series of books is great, too -- people sort of downplay them around here, because they're rather silly, but they teach great concepts and I've been surprised how well their lessons have remained with me over the years. Try the OO title. And spend some time futzing around with JavaScript, too. Maybe have a look at Douglas Crockford's work. It'll click. Just give it some time.

Christian Nunciato
+3  A: 

My "click" didn't happen directly in relationship to C#, but there were three instances that I believe relate to my ability to easily work within C#.

1) I was 8 years old, trying to write a seemingly simple assembly routine to clear the graphics screen on a Commodore 64. At the point where I would have written a loop in Basic, I hit a wall. As far as I understood things, there was no way to write a loop in assembly language that would cross the 256 (single-byte) barrier. I hunted through the books that I had, and just couldn't find the solution. (The answer certainly wasn't to write a 3-byte "line" of code for each group of 256 rows of pixels.) Several days later, it just hit me. (The solution was to write two loops, with the outer loop actually changing the code of the inner loop.) This isn't something we need to do with our current languages, but I could almost feel my brain growing.

2) This happened sometime while I was pretty young, too. (Maybe 10?) My piano lessons had progressed to a point where I had to play a song with different rhythms in each hand. I struggled with that song for weeks (partly because I tended to avoid the necessary practice). Practice helped, but not quite enough. Then, one day, I sat down and it suddenly clicked. Ever after that, the song was almost easy to play.

3) During college, and after I had been programming for fun for a few years, my instructor provided us with an entry-level OOP assignment. We were to use an object, which contained several other objects. Each of these drew themselves on-screen. To complete the task, everything needed to rotate by 45 degrees. Almost all the students (including myself) got partial credit because we rotated each object inside the containing object. The ones who got full credit had simply rotated one thing: the containing object. I didn't hear a "click", but this lesson definitely helped me to understand OOP.

To break your own barrier, you could follow the suggestions above. Maybe find a simple project you clearly understand, and implement it in C#. Or you could take a physical object you understand fairly well (like a car with steering wheel, wheels, engine, brakes, etc.), and model it with classes in C#. Of course, you may also achieve the "click" by simply picking one feature or keyword whose purpose you don't get, and studying that until it clicks. That one click may be enough to break into C# completely.

Either way, have fun! (Fun things are always easier for your subconscious mind to analyze while you aren't focusing on it.)

John Fisher
+3  A: 

First question: how many hours are you coding per week?

Second Question: who do you know in real life who DOES get it? Go talk to them!!!


Object oriented programming is a way of programming that organizes and minimizes repeating yourself. This makes for less code, and easier to alter code (because everything is only on one spot).

You are having problems with it, so I can assume you aren't grokking the need for inheritance. Inheritance is a way to reduce repeat code. And the other main part of OOP is classes. The point of classes is to group things in ways that keeps them nicely organized, and also keeps them encapsulated to reduce coupling (thus making changing code easier!)

That's pretty much all there is too it.

Now go out and program stuff 24/7 and find anyone in real life who really understands this stuff and talk their ear off.

Good luck.

Alex Baranosky
I am groking it. I understand inheritance, encapsulation, polymorphism, etc. It's putting it all together that I'm struggling with. Kind of like having all the ingredients for a pie, but not being able to make one yourself. I don't want to just be a recipe follower...
It sounds to me that you are NOT grokking, it. It sounds like you have it understood intellectually but not empathizing/feeling/sensing/being OOP. Maybe the solution is just to work on expansive enough projects that force you to take it all in and use it all at once???
Alex Baranosky
+2  A: 

Off topic, do you know where you got that phrase, "the a-ha moment": is it from a book, from someone else, or is it original? Because I think I remember someone's using that same phrase, when I was studying OOP and C++, online in about 1994.

Anyway: your question.

Like yours, my programming experience predates OOP: I did some Basic programming too, and, C.

It was, in a way, as you said, "a very linear approach to coding".

I was programmng professionally, in C, when I started to learn C++. So in terms of being able to "sit down, open up VS2008, and start coding", I was kind of already doing that, every day: I was sitting down and coding, in C.

It was event-driven programming: the software was reacting to events, to input: from the network, from various devices, from the UI ... so in that way, even this C code wasn't at all as linear as the kind of imperative Basic code ("read a keystroke, write to the screen") that we'd use to write.

So that's one thing: event-driven programming. Event-driven programming is not linear, it can be kind of difficult to conceptualize: a bunch of event-handlers, some independent, some interacting with each in a non-fixed sequence. Event-driven programming is not OOP (you can write event-driven programs in C), but one of the things that OOP is known to be good at is GUIs and event-driven programming. I suggest that OOP doesn't necessarily make it easy: the problem can be inherently difficult, and OOP makes it easier, not easy.

So that's another thing: if you can do it at all, then you're doing something right. Don't expect that everything will always be easy. A good solution might make the solution look easy and obvious, but developing a good solutions to large, difficult problems isn't easy, and we might thank OOP for making it possible to do at all.

Anyway, back to my story: I was coding in C. I learned incrementally to use C++, for example:

  • I have a bunch of data (structs), and a bunch of functions which operate on that data ... put the functions in the same structs as the data which they operate on, and "functions" become "methods"
  • Now that data has associated methods which are supposed to act on that data, make the data private so that other methods can't touch it directly ... encapsulation and/or information hiding
  • Now that I have well-defined classes (some of which already contain each other as data members), start using inheritance to implement similarities and dissimilarities between different types

For me, one of the "a-ha" moments was that we were driving drivers for different kinds of fax device, which each had different low-level APIs. Using OOP we could write ...

  • A simple, abstract class, which declared the simple, high-level API (like, sendFax, receiveFax, cancel, etc.) which we wanted all devices to support
  • Subclasses, which used the API of the specific hardware to implement the abstract API inherited from the abstract base class.

I've just remembered something else. When I was learning C++, I read various books:

  • Thinking in C++ to learn to read the syntax of C++
  • Effective C++ to learn various canonical tactical mistakes to avoid when writing C++

Having read these, and with about 6 months' practice, I could use C++ as a better C.

One of the next books I read though was Design Patterns by the Gang of Four: and reading that book was an "a-ha" moment for me, it made me think, "if those other books showed me how to write in an object-oriented programming language, this book is showing me why I would want to."

So, there's a recommendation: read Design Patterns.

I've been talking about C++ and so on because that was the era in which I had my first a-has. I think it's relevent ... knowing OOP and C++ well, it took me less than a week to "sit down, open up VS2008, and start coding" in C# when that came along.

I'm not sure where "a-ha" moment came from. Perhaps it's a regional thing? I did grow up in California where "dude" is part of the vernacular after all.I get event-driven coding and perhaps, looking back at what I've actually been accomplishing in C#, that's what I'm doing.
+2  A: 
  1. You need something that you need/want to accomplish.
  2. Sit down and create it.
  3. While you are creating it you will have to figure out the things you don't know. It's probably the best way to identify what those things are.
  4. When you are done and have something working you look back on it and think about what you could have done differently to organize it better.
  5. Do some research about those specific things and possible ways to approach it.
  6. Create something else and reflect on that.
  7. Repeat until you have an a-ha moment.

For me my first a-ha moment was being taught Honeywell assembler during my 3rd week of training and finally realizing how the computer really worked.

My OOP a-ha moment was during a Real Time Relay Ladder Logic course and I decided to make a library to simulate the Texas Instrument hardware that we had to write our programs against. It let me write/test my programs for the class without having to go to the school and use the real hardware. It opened my eyes to OOP. I believe the a-ha moment happened because I was able to model (with code) something that was real.

+1  A: 

The following didn't make OO click for me (it already had when I heard it), but I did find it a very nice nutshell description.

A collegue of mine is fond of quoting a statement from one of his college professors, which went something like this:

Write out a grid with the rows labeled by data types and the columns labeled by operations on the data. If you slice your implementation horizontally, you're doing object-oriented programming. If you slice it vertically, you're doing functional programming.

Try thinking of OO as a way to organize your code in which the implementation of an operation on a programmer-defined data type is bundled into the definition of the data.

+2  A: 

I think the a-ha moment for me, was when I stopped thinking about OOP in terms of cars and blueprints, and whatever other metaphors my teachers were trying to crowbar into my brain, and started thinking about it in terms of its practical application in real code.

The first object I wrote in which I really got it, was a little class that created a database connection, and encapsulated a bunch of methods for doing SQL queries. After that point OOP went from something the teachers talked about, into being something that was actually useful to me and my code.

So, my advice would be, just to keep on going, keep learning and, most importantly, write as much code as you can. What makes something click for me, or for everyone else, may not make it click for you, so you need to forge your own path.

As someone else suggested, maybe drop C# for a little while, and try a different language. Broaden your horizons, maybe learn some C++, or have a mess around with Python or Ruby. You will come back to C# with a fresh perspective and clear palette, and as a better programmer, and maybe things will become more clickable for you then.

+1  A: 

Object Oriented design in general requires mental snuggling, but for me C-type OOD seemed rather natural after the university using JAVA to teach us OOD.

After much practice with hobby projects where an elegant architecture is required to meet some of the use cases - OOP seem to become more and more automatic.

+1  A: 

Well, this is how I see your problem. The fact that you came from SQL, a 4GL (fourth generation language) which closer to human language than a 3GL such as C#, is like somebody use to drive airplane doesn’t get what’s a big deal to drive a car. You should either try to learn how to bike (a 2GL like assembly language) or try to drive a lower end car (such as Fortan or C ) to appreciate a language like C#.

+2  A: 

as a previous poster mentioned, do check out design patterns.

also, i found uncle bob's stuff useful as a student as well as an instructor, in particular some of the oo design principles: http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod

Ray Tayek
+2  A: 

Learning what Generics in C# are did it for me. Now I forever think in if-else statements.

+1  A: 

There are lots of good suggestions here, though only Mr. Sampson has hinted that it would be beneficial to find the right people to answer questions. I can't count how many times I've been watching someone work, interrupted them to ask a question along the lines of, "why did you do X?" and have an a-ha moment shortly thereafter. Not always, but ask enough people enough questions, and the mind-meld will happen, and it's great when it does.

+2  A: 

Try this: find a big switch statement and refactor it into classes. This was a big 'aha!' moment for me. It is a classic refactoring, illustrates the difference between procedural and OO design, and is not difficult to perform. Then realise that if statements are small switches.

Now, go and read about design patterns. Write some classes using them.

Next, take some set of classes that provide some functionality and rewrite it without return statements and preferably with interfaces. This was another big 'aha!' for me.

In fact, a good bet is to spend a week reading c2.com.

Hope helps you on your journey.

This answer kills. That's STILL how I make my OO code even more OO: by constantly finding ways to change IFs for polimorphism.
+1  A: 

My "a-ha" moment about OOP came from working with the .NET framework. At first, I was annoyed at how clumsy it was to write text to a file. Then I realized that I didn't need to make the decision of whether or not my object was going to print to a file; I could just make it use a TextWriter, and let whatever created it decide where the output was going to go to a file or to the console. Then I realized how easy it was to make a subclass of TextWriter that sent output to a TextBox. And then I realized that kind of thinking underlay all of the design of the framework.

Suddenly (and this was pretty sudden, like it happened over a weekend) the framework made sense in a way it absolutely hadn't before. And I also realized that it was easy to use the same principles that the framework's designers had used in designing my own programs.

Robert Rossney
+1  A: 

Perhaps the challenge you're facing is that you are too familiar with SQL. OO and Relational are two concepts at odds with each other. With relational tools you're mostly focused on the data and how it's represented. Each programming task concerns handling the data in the way that accomplishes the required task.

OO on the other hand concerns behavior. a programming task in an OO system concerns invoking the behaviors in the proper instances to get the task done, and to design object classes that will behave in expected ways.


Interfaces. I understood the basics of OOP and inheritance when I first started using, but interfaces took an unreasonably long time for me to grasp.

The first time I heard about these things, I immediately said to myself "why on earth would I ever need to create a pseudoclass-thingy {my pet name for interfaces} that doesn't have any implementation? Isn't that the whole point of inheritance, so that I don't have to re-type the same implementation logic over and over?"

So, one day I said to myself, "I wonder how you write methods which are generalized across all types which have a particular method, without having to sacrifice type safety". Then it occurred to me: that's exactly what interfaces are used for! Once I understood that, everything made sense, and on my own I'd invented a few design patterns which closely resembled factory and observer patterns.

That's when it clicked with me, and I was able to think about OOP on an entirely different level.


Hmmm, factories and the singleton pattern did it for me. I still have trouble though, I do feel that I'm not using the full OO capabilities but it's always a learning curve.

The thing that I have trouble with is figuring out what class should do what, e.g. should an employee object have a RaiseSalary method that takes an amount or should a PayMaster object have a method that takes a List of employees and calculates how much to raise their pay by? Tenuous example I know, but it's an example :P

Singletons are arguably a very risky pattern in OO terms as far as I know. They're very close to having a global variable/object, which isn't really OO.
Erik van Brakel

The thing that made OO click for me is learning about Prototype based OO like in Io and Self. C#'s OO is a very different beast: not elegant and simple, but hairy and complex. Simple doesn't mean less powerful, on the contrary! I suggest learning a simple and elegant system first. Then you can see the OO in C# if you squint.

Another A-Ha moment was understanding how a type system can prevent calling the wrong methods on the wrong objects at compile time. C#'s type system doesn't do this in all cases because of casts. I got this A-Ha moment when reading the articles on type theory from the Journal of Object Technology.

+1  A: 

This inflammatory article on why getters and setters are evil challenged how I thought I was doing OOP. A few of the points made in the article might be tenuous, but the idea of "tell, don't ask, when possible" revolutionized how I think about OO design and write my code.