Quantcast

Maximum PC

It is currently Sat Aug 30, 2014 7:42 am

All times are UTC - 8 hours




Post new topic Reply to topic  [ 14 posts ] 
Author Message
 Post subject: *sigh* why can't we have this in .NET?
PostPosted: Thu Jul 07, 2011 11:46 am 
Bitchin' Fast 3D Z8000
Bitchin' Fast 3D Z8000
User avatar

Joined: Mon Jun 14, 2004 4:04 pm
Posts: 985
Location: Earth
One of the things I love about Ruby is inspect(). Suppose you have an object that returns an array:

Code:
result_of_query = Products.find_by_type('Power Tools')


One of the cool things about Ruby is that you can view the contents of the array in interactive ruby (irb):

Code:
puts results_of_query.inspect


By calling the inspect method, you get a nifty output, say like this:

Code:
['Drill','Nail Gun', ...]


One thing I'm missing in .NET is this stuff. When I'm writing test, it'd be nice to be able to return a string with a neatly formatted output of anything that implements IEnumerable.

But instead of whining, I went ahead and created my own Inspect method. But wouldn't it be cumbersome if I had to do this EVERYTIME?

Code:
string output = Helper.Inspect(myCollection);


So, using the power of Extension Methods, I wrote a quick and dirty function:

Code:
public static string Inspect<T>(this IEnumerable<T> list)
{
     System.Text.StringBuilder sb = new StringBuilder();
     List<string> items = new List<string>();
     foreach (var item in list)
     {
        items.Add(item.ToString());
     }
     sb.Append(String.Join(",", items.ToArray()));
     sb.Insert(0, "[");
     sb.Insert(sb.Length, "]");
     return sb.ToString();
}


It's nothing big. The extension method allows me to call this method from any IEnumerable object:

Code:
  List<int> myInts = new List<int>();   myInts.Inspect();


The only caveat is that because I'm using a generic type, any of my custom types won't be able to utilize this. So, I ask the user to override the ToString() method. I also created another property that exposes the name and value of the property:

Code:
public static string InspectProperties<T>(this T obj)
{
   StringBuilder sb = new StringBuilder();

   Type type = obj.GetType();

   PropertyInfo[] properties = type.GetProperties();

   foreach (PropertyInfo property in properties)
   {
      sb.AppendFormat("\"{0}\": \"{1}\" \n", property.Name, property.GetValue(obj, null));
   }

   return sb.ToString();
}


I created another extension method that is accessible through any object. Now, I'm only exposing properties (not methods) and getting their values. I do this because I write a lot of State Bags (POCO) that I use to shuttle data between my BLL and DAL's.

Tell me what you think! I'd like to start a discussion on the things that you do that make your dev day-to-day easy.


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Thu Jul 07, 2011 2:59 pm 
SON OF A GUN
SON OF A GUN
User avatar

Joined: Mon Nov 01, 2004 5:41 am
Posts: 11605
DJSPIN80 wrote:
I'd like to start a discussion on the things that you do that make your dev day-to-day easy.
I'd be down like a clown, but I'd change the title :)

I haven't been too bothered by that. I haven't found a need to output the contents of an array like that. I know in Classic ASP and PHP I had to do that ALL the time, because their wasn't a good way to debug it. I have overridden .ToString() a few times, but typically it hasn't been a big deal.

Can you help me understand where this would be used? If I am debugging in .NET I just throw up a breakpoint and watch/quick watch the array.

Dumping the raw array like that isn't usually the prettiest way so I wouldn't use it for output to the user, personally.


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Fri Jul 08, 2011 4:15 am 
Bitchin' Fast 3D Z8000
Bitchin' Fast 3D Z8000
User avatar

Joined: Mon Jun 14, 2004 4:04 pm
Posts: 985
Location: Earth
CrashTECH wrote:
Can you help me understand where this would be used? If I am debugging in .NET I just throw up a breakpoint and watch/quick watch the array.
Dumping the raw array like that isn't usually the prettiest way so I wouldn't use it for output to the user, personally.


When I debug, I just call the Inspect method in the immediates window. I like watch/quickwatch, but I often have too many things I'm watching or if the array is too big then I actually search. I'm still building out the inspect method so that it's overloaded and can search items in the array (gonna try to improve it to do partial searches).

It's come in handy already. I built a small control where I'm returning a list of items. The problem is, the collection I'm returning is pretty big and I want to verify the contents so I use it to search through it in the immediates window.


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Sat Jul 09, 2011 12:31 pm 
SON OF A GUN
SON OF A GUN
User avatar

Joined: Mon Nov 01, 2004 5:41 am
Posts: 11605
Post the whole class file?


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Mon Jul 11, 2011 3:38 am 
Bitchin' Fast 3D Z8000
Bitchin' Fast 3D Z8000
User avatar

Joined: Mon Jun 14, 2004 4:04 pm
Posts: 985
Location: Earth
CrashTECH wrote:
Post the whole class file?


Code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Utility.Extensions.Lists
{
    public static class MyExtensions
    {
        /// <summary>
        /// Inspects the array by printing out the contents of any object that implements IEnumerable.
        /// This works similar to Ruby's [].inspect method.  Be aware that if you're passing an IEnumerable
        /// of some custom defined type.  Please override the ToString() method to expose the data elements that aid
        /// you in debugging.
        /// Da Bears!
        /// </summary>
        /// <typeparam name="T">Da type</typeparam>
        /// <param name="list">Da list</param>
        /// <returns>Da results</returns>
        public static string Inspect<T>(this IEnumerable<T> list)
        {   
            System.Text.StringBuilder sb = new StringBuilder();
            List<string> items = new List<string>();
            foreach (var item in list)
            {
                items.Add(item.ToString());
            }
            sb.Append(String.Join(",", items.ToArray()));
            sb.Insert(0, "[");
            sb.Insert(sb.Length, "]");
            return sb.ToString();
        }
        public static string Inspect<T>(this IList<T> list, T search)
        {
            if (list.Contains<T>(search))
            {
                int index = list.IndexOf(search);
                List<T> _temp = new List<T>();
                _temp.Add(list[index]);
                return Inspect<T>(_temp);
            }
            else
                return Inspect(new List<T>()); // return an empty array
        }
    }
}


Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Reflection;

namespace Utility.Extensions.Objects
{
    public static class ObjectExtensions
    {

        public static string InspectProperties<T>(this T obj)
        {
            StringBuilder sb = new StringBuilder();

            Type type = obj.GetType();

            PropertyInfo[] properties = type.GetProperties();

            foreach (PropertyInfo property in properties)
            {
                sb.AppendFormat("\"{0}\": \"{1}\" \n", property.Name, property.GetValue(obj, null));
            }

            return sb.ToString();
        }
    }
}


CAVEAT: I'm still working on this and building out functionality as I need it.


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Wed Jul 13, 2011 9:01 am 
SON OF A GUN
SON OF A GUN
User avatar

Joined: Mon Nov 01, 2004 5:41 am
Posts: 11605
You may be on to something..

This is something that I added to an error logging class that dealt with a lot of individual data rows:

Code:
public static string DataRowToString(DataRow dr)
{
   string dataRowAsString = string.Empty;

   try
   {
      for (int i = 0; i < dr.Table.Columns.Count; i++)
      {
         dataRowAsString += string.Format("[Colname: {0} / Value: {1}] ", dr.Table.Columns[i].ColumnName, dr[i]);
      }
   }
   catch (Exception e)
   {
      dataRowAsString += string.Format("\n\nFailed to convert DataRow to string: {0}", e);
   }

   return dataRowAsString;
}


The reason the exception is a += is it lets me know if it failed part way through or right at the start. I still get some data out. Since this was for logging anyway....


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Thu Jul 14, 2011 5:46 pm 
Bitchin' Fast 3D Z8000
Bitchin' Fast 3D Z8000
User avatar

Joined: Mon Jun 14, 2004 4:04 pm
Posts: 985
Location: Earth
One more thing I want to add to my extensions, is the concept of Any and Empty.

I hate having to ask this bloody question every time:

Code:
if (collection.Count >0)


I'm all about readability, so I'm going to add two new methods to my extension file:

Code:
public static bool Any(this IEnumerable<T> list)
{
   return (list.Count > 0 ? true : false);
}


Code:
public static bool Empty(this IEnumerable<T> list)
{
  return (list.Count == 0 ? true : false);
}


You're probably wondering how to justify this? Well, in testing:

Code:
public void ListShouldNotBeEmpty()
{
   // Some code...
   Assert.AreEqual<bool>(true, myCollections.Any());
}


Any and Empty are inverses that really do the same thing. What it is, however, is syntactic sugar. Code that's easy to read is code that's easy to maintain. While these two are simply icing on the cake, I'm sure that your successor will love you when they see:

Code:
if (mylist.Empty() == false)

As opposed too...
Code:
if (mylist.Count > 0)


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Fri Jul 15, 2011 7:26 pm 
SON OF A GUN
SON OF A GUN
User avatar

Joined: Mon Nov 01, 2004 5:41 am
Posts: 11605
I could see that being useful.


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Sun Jul 17, 2011 8:46 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
DJSPIN80 wrote:
One of the things I love about Ruby is inspect(). Suppose you have an object that returns an array:
Code:
result_of_query = Products.find_by_type('Power Tools')

One of the cool things about Ruby is that you can view the contents of the array in interactive ruby (irb):
Code:
puts results_of_query.inspect

By calling the inspect method, you get a nifty output, say like this:
Code:
['Drill','Nail Gun', ...]

Wow, the more you bring up Ruby examples, the more I see Lisp in Ruby. How does the inspect method know to print the product name and exclude any other fields in the class? Or is it slots in the structure like in CL?

Example...
Code:
CL-USER> (defstruct product name type (in-stock t))
PRODUCT
CL-USER> (setf products (list (make-product :name 'drill :type 'power-tool)
               (make-product :name 'nail-gun :type 'power-tool)
               (make-product :name 'pepsi :type 'beverage)))
(#S(PRODUCT :NAME DRILL :TYPE POWER-TOOL :IN-STOCK T)
#S(PRODUCT :NAME NAIL-GUN :TYPE POWER-TOOL :IN-STOCK T)
#S(PRODUCT :NAME PEPSI :TYPE BEVERAGE :IN-STOCK T))
CL-USER> (remove-if-not #'(lambda (x) (equal (product-type x) 'power-tool)) products)
(#S(PRODUCT :NAME DRILL :TYPE POWER-TOOL :IN-STOCK T)
#S(PRODUCT :NAME NAIL-GUN :TYPE POWER-TOOL :IN-STOCK T))
CL-USER> (mapcar #'(lambda (x) (product-name x))
       (remove-if-not #'(lambda (x) (equal (product-type x) 'power-tool)) products))
(DRILL NAIL-GUN)


DJSPIN80 wrote:
The only caveat is that because I'm using a generic type, any of my custom types won't be able to utilize this. So, I ask the user to override the ToString() method.

The C# lingo is confusing me. What is the difference between a generic type and a custom type? Is custom/generic referring to class inheritance? Boxing and unboxing of primitive and object types?

DJSPIN80 wrote:
Tell me what you think! I'd like to start a discussion on the things that you do that make your dev day-to-day easy.

I think that you should find a job programming in Ruby! You seem to like the language features. You're also a good candidate for CL.


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Sun Jul 17, 2011 9:00 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
DJSPIN80 wrote:
I'm all about readability, so I'm going to add two new methods to my extension file:

Code:
public static bool Any(this IEnumerable<T> list)
{
   return (list.Count > 0 ? true : false);
}


Code:
public static bool Empty(this IEnumerable<T> list)
{
  return (list.Count == 0 ? true : false);
}

Alright, now you're just being a CL thief! =)

From the CL hyperspec:
every returns false as soon as any invocation of predicate returns false. If the end of a sequence is reached, every returns true. Thus, every returns true if and only if every invocation of predicate returns true.

some returns the first non-nil value which is returned by an invocation of predicate. If the end of a sequence is reached without any invocation of the predicate returning true, some returns false. Thus, some returns true if and only if some invocation of predicate returns true.

notany returns false as soon as any invocation of predicate returns true. If the end of a sequence is reached, notany returns true. Thus, notany returns true if and only if it is not the case that any invocation of predicate returns true.

notevery returns true as soon as any invocation of predicate returns false. If the end of a sequence is reached, notevery returns false. Thus, notevery returns true if and only if it is not the case that every invocation of predicate returns true.

Code:
CL-USER> (every #'product-p products)  ;The function product-p returns true if the arg is a product - It was created automagically by the macro that defined a product (previously)
T
CL-USER> (every #'integerp products)
NIL
CL-USER> (some #'product-p products)
T
CL-USER> (some (lambda (x) (equal (product-type x) 'beverage)) products)
T
CL-USER> (every (lambda (x) (equal (product-type x) 'beverage)) products)
NIL
CL-USER> (notany (lambda (x) (equal (product-type x) 'beverage)) products)
NIL
CL-USER> (notevery (lambda (x) (equal (product-type x) 'beverage)) products)
T

Why don't you just go ahead and implement first (ie car) and rest (ie cdr) operations for working on lists while you're at it?!

THIEF!!!! =)


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Sun Jul 17, 2011 9:07 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
Hmm... for some reason the forum didn't post my second response.
CrashTECH wrote:
Can you help me understand where this would be used? If I am debugging in .NET I just throw up a breakpoint and watch/quick watch the array.

Transaction logging, report generation, serialization, etc.

Debuggers are great when working with a compiled language and IDE, but interactive development benefits tremendously from useful information being printed to the screen. I'm not sure how this applies to C# though. Are there interactive C# environments? For the testing example that DJSpin has given, I'd think that he'd also want to be able to filter (yeah, steal that one too you thief!) a list and print the actual constructor code instead of just a pretty-print type of output.


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Mon Jul 18, 2011 5:16 am 
Bitchin' Fast 3D Z8000
Bitchin' Fast 3D Z8000
User avatar

Joined: Mon Jun 14, 2004 4:04 pm
Posts: 985
Location: Earth
Gadget wrote:
Wow, the more you bring up Ruby examples, the more I see Lisp in Ruby. How does the inspect method know to print the product name and exclude any other fields in the class? Or is it slots in the structure like in CL?

Because Ruby was inspired by CL. :) Matz had a lot of respect for CL, so when he was developing Ruby he really kept a lot of these things in mind.

Quote:
I think that you should find a job programming in Ruby! You seem to like the language features. You're also a good candidate for CL.


I'm looking, actually. :P I've been unsuccessful, but the more I write Ruby and get better at it (and developing Rails apps), the better it'll be for me. I'm working on a pro-bono project right now, I figured nothing bad will come out of it.


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Mon Jul 18, 2011 5:21 am 
Bitchin' Fast 3D Z8000
Bitchin' Fast 3D Z8000
User avatar

Joined: Mon Jun 14, 2004 4:04 pm
Posts: 985
Location: Earth
Gadget wrote:
Debuggers are great when working with a compiled language and IDE, but interactive development benefits tremendously from useful information being printed to the screen. I'm not sure how this applies to C# though. Are there interactive C# environments? For the testing example that DJSpin has given, I'd think that he'd also want to be able to filter (yeah, steal that one too you thief!) a list and print the actual constructor code instead of just a pretty-print type of output.


C# has an interactive environment, it's called Visual Studio. :P But since C# is compiled, we can debug/breakpoint and see what's happening.

The problem occurs in production environments. I tend to lean towards data rich exceptions; the more info I can read, the better my debugging becomes. The inspect methods I wrote are to simplify debugging in production. In my orgs case, even though I can touch production, I don't like to make changes to it. So if I can debug my app by reading through logs then all the better. I should be able to see the contents of an object in my logs and be able to determine why it failed.

Oh and to answer your question about generics and custom type.

Generics in C# are, for a lack of a better example, template types in C++.

Code:
List<T>


In C#, your objects can have multiple generic types.

Code:
public TResult MyMethod<TResult, TInput>(TInput t)


Unlike custom types, a generic type is just that - generic. You can plug in your custom type as the type that the method/class will operate on.


Top
  Profile  
 
 Post subject: Re: *sigh* why can't we have this in .NET?
PostPosted: Mon Jul 18, 2011 6:49 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
DJSPIN80 wrote:
C# has an interactive environment, it's called Visual Studio. :P

Haha... good one. Now I'm going to spend the next month correcting all the .NETters about VS and interactive programming. Curse you!

DJSPIN80 wrote:
Generics in C# are, for a lack of a better example, template types in C++.

Gotcha. Java also has generics. The 'custom type' lingo confused me as you're not actually 'customizing' anything. In Java lingo, a generic class or generic type declaration is instantiated using a 'type variable' or 'type parameter'. More MS naming confusion -- It's not called a thread; It's a fiber (unless you're using Win64 where it is called an osFiber64).

In Java 7, they've added operators and wildcards for 'simplifying' generics. Things like <? extends MyClass> and <? super MyClass> where the ? is a wildcard operator allowing me to extend my generic type, the <> operator for when I'm too lazy to type in <SomeClass> a second time, and quite a few other 'features'. Personally, I've felt for quite a while now that OOP in mainstream languages is becoming rather cumbersome, and less expressive, as it moves farther away from the message passing design that Alan Kay had originally envisioned. Objects are the (not so) new square peg.


Top
  Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC - 8 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group