tags:

views:

156

answers:

2

I woudl like to know how to use a System.Collections.Hashtable in F#. The reason it is a Hashtable is because I am referencing C# assemblies.

How would I call the following methods? - Add - Get value from key

I have not been able to find anything useful in google about this. Any help would be appreciated.

Thanks

+2  A: 

It's pretty straightforward to do.

open System.Collections //using System.Collections

let ht = Hashtable() // var ht = new Hashtable()

ht.Add(1, "One")

let getValue = ht.Item[1] // var getValue = ht[1];
//NB: All indexer properties are named "Item" in F#.
Mark H
If you wanted to call `Item` directly, then the syntax would be `ht.Item(1)`. However, it is possible to access indexers directly from F# using `ht.[1]`.
Tomas Petricek
Thanks for the correction. As you can tell, I've only just started with F#.
Mark H
No problem. Welcome and have fun learning F#! The language has been changing quite a bit during the finalization of VS 2010 - there were times when you had to use `Item` explicitly, so information on the internet can be sometimes confusing :-).
Tomas Petricek
Thanks guys, it would be nice for the .Net collections to be accessible in the same way as native F# collections. Maybe you can and I am still not practiced enough.
Russell
+8  A: 

As Mark points out, you can work with the Hashtable type directly from F# (just like with any other .NET type). The syntax for accessing indexers in F# is slightly different though:

open System.Collections 

// 'new' is optional, but I would use it here
let ht = new Hashtable()
// Adding element can be done using the C#-like syntax
ht.Add(1, "One")  
// To call the indexer, you would use similar syntax as in C#
// with the exception that there needst to be a '.' (dot)
let sObj = ht.[1] 

Since Hashtable is not generic, you would probably want to cast the object back to string. To do that, you can either use the :?> downcast operator, or you can use the unbox keyword and provide a type annotation to specify what type do you want to get as the result:

let s = (sObj :?> string)
let (s:string) = unbox sObj

If you have any control over what type is used, then I would recommend using Dictionary<int, string> instead of Hashtable. This is fully compatible with C# and you would avoid the need to do casting. If you're returning this as a result from F#, you could also use standard F# map and just upcast it to IDictionary<_,_> before passing it to C#:

let map = Map.empty |> Map.add 1 "one"
let res = map :> IDictionary<_, _>

This way, C# users will see a familiar type, but you can write the code in the usual functional style.

Tomas Petricek
THanks, the upcast and .[""] syntax helped me resolve it. The trick was taking the obj dict[] to a Hashtable dict[]. :)
Russell
Isn't :> the upcast operator? http://msdn.microsoft.com/en-us/library/dd233220.aspx
Artefacto
@Artefacto: Yes, you're right. I'll correct the answer (hopefuly I'll eventualy remember which one is which...).
Tomas Petricek