Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 173193
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 11, 20262026-05-11T13:18:00+00:00 2026-05-11T13:18:00+00:00

Need to convert the following code from Ruby to C#. However I’m kind of

  • 0

Need to convert the following code from Ruby to C#. However I’m kind of puzzled by the use of the yield keyword and the general syntax of Ruby. Can anyone that knows a little bit Ruby please help out and convert the code

class < < Cache STALE_REFRESH = 1 STALE_CREATED = 2  # Caches data received from a block # # The difference between this method and usual Cache.get # is following: this method caches data and allows user # to re-generate data when it is expired w/o running # data generation code more than once so dog-pile effect # won't bring our servers down # def smart_get(key, ttl = nil, generation_time = 30.seconds)   # Fallback to default caching approach if no ttl given   return get(key) { yield } unless ttl    # Create window for data refresh   real_ttl = ttl + generation_time * 2   stale_key = '#{key}.stale'    # Try to get data from memcache   value = get(key)   stale = get(stale_key)    # If stale key has expired, it is time to re-generate our data   unless stale     put(stale_key, STALE_REFRESH, generation_time) # lock     value = nil # force data re-generation   end    # If no data retrieved or data re-generation forced, re-generate data and reset stale key   unless value     value = yield     put(key, value, real_ttl)     put(stale_key, STALE_CREATED, ttl) # unlock   end    return value end 

end

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. 2026-05-11T13:18:01+00:00Added an answer on May 11, 2026 at 1:18 pm

    I don’t know C# at all, so anything I say about C# should be taken with a grain of salt. However, I will try to explain what goes on in that piece of Ruby code.

    class << Cache 

    Ruby has something called singleton methods. These have nothing to do with the Singleton Software Design Pattern, they are just methods that are defined for one and only one object. So, you can have two instances of the same class, and add methods to one of those two objects.

    There are two different syntaxes for singleton methods. One is to just prefix the name of the method with the object, so def foo.bar(baz) would define a method bar only for object foo. The other method is called opening up the singleton class and it looks syntactically similar to defining a class, because that’s also what happens semantically: singleton methods actually live in an invisible class that gets inserted between the object and its actual class in the class hierarchy.

    This syntax looks like this: class << foo. This opens up the singleton class of object foo and every method defined inside of that class body becomes a singleton method of object foo.

    Why is this used here? Well, Ruby is a pure object-oriented language, which means that everything, including classes is an object. Now, if methods can be added to individual objects, and classes are objects, this means that methods can be added to individual classes. In other words, Ruby has no need for the artificial distinction between regular methods and static methods (which are a fraud, anyway: they aren’t really methods, just glorified procedures). What is a static method in C#, is just a regular method on a class object’s singleton class.

    All of this is just a longwinded way of explaining that everything defined between class << Cache and its corresponding end becomes static.

      STALE_REFRESH = 1   STALE_CREATED = 2 

    In Ruby, every variable that starts with a capital letter, is actually a constant. However, in this case we won’t translate these as static const fields, but rather an enum, because that’s how they are used.

      # Caches data received from a block   #   # The difference between this method and usual Cache.get   # is following: this method caches data and allows user   # to re-generate data when it is expired w/o running   # data generation code more than once so dog-pile effect   # won't bring our servers down   #   def smart_get(key, ttl = nil, generation_time = 30.seconds) 

    This method has three parameters (four actually, we will see exactly why later), two of them are optional (ttl and generation_time). Both of them have a default value, however, in the case of ttl the default value isn’t really used, it serves more as a marker to find out whether the argument was passed in or not.

    30.seconds is an extension that the ActiveSupport library adds to the Integer class. It doesn’t actually do anything, it just returns self. It is used in this case just to make the method definition more readable. (There are other methods which do something more useful, e.g. Integer#minutes, which returns self * 60 and Integer#hours and so on.) We will use this as an indication, that the type of the parameter should not be int but rather System.TimeSpan.

        # Fallback to default caching approach if no ttl given     return get(key) { yield } unless ttl 

    This contains several complex Ruby constructs. Let’s start with the easiest one: trailing conditional modifiers. If a conditional body contains only one expression, then the conditional can be appended to the end of the expression. So, instead of saying if a > b then foo end you can also say foo if a > b. So, the above is equivalent to unless ttl then return get(key) { yield } end.

    The next one is also easy: unless is just syntactic sugar for if not. So, we are now at if not ttl then return get(key) { yield } end

    Third is Ruby’s truth system. In Ruby, truth is pretty simple. Actually, falseness is pretty simple, and truth falls out naturally: the special keyword false is false, and the special keyword nil is false, everything else is true. So, in this case the conditional will only be true, if ttl is either false or nil. false isn’t a terrible sensible value for a timespan, so the only interesting one is nil. The snippet would have been more clearly written like this: if ttl.nil? then return get(key) { yield } end. Since the default value for the ttl parameter is nil, this conditional is true, if no argument was passed in for ttl. So, the conditional is used to figure out with how many arguments the method was called, which means that we are not going to translate it as a conditional but rather as a method overload.

    Now, on to the yield. In Ruby, every method can accept an implicit code block as an argument. That’s why I wrote above that the method actually takes four arguments, not three. A code block is just an anonymous piece of code that can be passed around, stored in a variable, and invoked later on. Ruby inherits blocks from Smalltalk, but the concept dates all the way back to 1958, to Lisp’s lambda expressions. At the mention of anonymous code blocks, but at the very least now, at the mention of lambda expressions, you should know how to represent this implicit fourth method parameter: a delegate type, more specifically, a Func.

    So, what’s yield do? It transfers control to the block. It’s basically just a very convenient way of invoking a block, without having to explicitly store it in a variable and then calling it.

        # Create window for data refresh     real_ttl = ttl + generation_time * 2     stale_key = '#{key}.stale' 

    This #{foo} syntax is called string interpolation. It means ‘replace the token inside the string with whatever the result of evaluating the expression between the braces’. It’s just a very concise version of String.Format(), which is exactly what we are going to translate it to.

        # Try to get data from memcache     value = get(key)     stale = get(stale_key)      # If stale key has expired, it is time to re-generate our data     unless stale       put(stale_key, STALE_REFRESH, generation_time) # lock       value = nil # force data re-generation     end      # If no data retrieved or data re-generation forced, re-generate data and reset stale key     unless value       value = yield       put(key, value, real_ttl)       put(stale_key, STALE_CREATED, ttl) # unlock     end      return value   end end 

    This is my feeble attempt at translating the Ruby version to C#:

    public class Cache<Tkey, Tvalue> {     enum Stale { Refresh, Created }      /* Caches data received from a delegate      *      * The difference between this method and usual Cache.get      * is following: this method caches data and allows user      * to re-generate data when it is expired w/o running      * data generation code more than once so dog-pile effect      * won't bring our servers down     */     public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)     {         // Create window for data refresh         var realTtl = ttl + generationTime * 2;         var staleKey = String.Format('{0}stale', key);          // Try to get data from memcache         var value = Get(key);         var stale = Get(staleKey);          // If stale key has expired, it is time to re-generate our data         if (stale == null)         {             Put(staleKey, Stale.Refresh, generationTime); // lock             value = null; // force data re-generation         }          // If no data retrieved or data re-generation forced, re-generate data and reset stale key         if (value == null)         {             value = strategy();             Put(key, value, realTtl);             Put(staleKey, Stale.Created, ttl) // unlock         }          return value;     }      // Fallback to default caching approach if no ttl given     public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) =>          Get(key, strategy);      // Simulate default argument for generationTime     // C# 4.0 has default arguments, so this wouldn't be needed.     public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) =>          SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);      // Convenience overloads to allow calling it the same way as      // in Ruby, by just passing in the timespans as integers in      // seconds.     public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) =>          SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);      public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) =>          SmartGet(key, new TimeSpan(0, 0, ttl), strategy); } 

    Please note that I do not know C#, I do not know .NET, I have not tested this, I don’t even know if it is syntactically valid. Hope it helps anyway.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 104k
  • Answers 104k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer You can use the UIScrollView's setContentOffset:animated: function to scroll to… May 11, 2026 at 8:30 pm
  • Editorial Team
    Editorial Team added an answer jQuery has javascript template plugins like jBind and jTemplate. I… May 11, 2026 at 8:30 pm
  • Editorial Team
    Editorial Team added an answer The mapping itself is done this way: :map ; A;<esc>… May 11, 2026 at 8:30 pm

Related Questions

Need to convert the following code from Ruby to C#. However I'm kind of
I have been creating a website with Ruby on Rails, and will be hosting
I'm trying to convert the following code from OpenGL 1.5 spec. to the OpenGLES
I've got a method which currently takes an IList as a parameter, where UserBO
I need to convert several million dates stored as wide strings into boost dates

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.