Could anyone please give me a short working example of a C# class which can be compiled to a DLL, and an example of VB.NET-code creating an object based on this class and using its members (methods). The C# class has to have a namespace, at least one class definition (obviously) and some methods or whatever they ought to be called. I have someone else's code of a C#-DLL but cannot see its members in my VB-project. I know I have to make a reference to the DLL in my VB.NET project. I'm using VB.NET Express 2008 and C# 2008 Express.
-
Do you have the code? or just the DLL? – WernerCD Oct 29 '10 at 14:26
-
This is not a dup, but it is a followup to http://stackoverflow.com/questions/4044032/how-to-call-a-c-classs-static-method-from-vb-net – Steve Townsend Oct 29 '10 at 14:27
-
It should work in general, you need to be more specific about what DLL and/or what members you can not see. How can you not "see" them? In the object browser, intellisense or what? – Albin Sunnanbo Oct 29 '10 at 14:28
-
@WernerCD: I have the code and built the DLL using C# Express 2008. – George Oct 29 '10 at 14:30
-
@Steve Townsend: That's right but I got stuck, I guess I still don't know enough about C# and VB.NET in this regard. – George Oct 29 '10 at 14:32
-
@iar - That's fine, just wanted people to see the context. Good luck, I cannot see why this is not working for you :-( – Steve Townsend Oct 29 '10 at 14:33
-
@Albin Sunnanbo: Forget about me not being able to "see" the members of the DLL I mentioned. All I ask is a working example of a C# DLL being used in VB.NET. – George Oct 29 '10 at 14:34
-
@iar - I got your code running, see below for details. – Steve Townsend Oct 29 '10 at 15:11
5 Answers
--foo.cs
namespace Sharp
{
public class Foo
{
public string Message
{
get { return "This is from CSharp"; }
}
}
}
--bar.vb
Namespace bartest
Public Class Bar
Public Shared Sub Main()
Dim test as Sharp.Foo
test = New Sharp.Foo()
Console.WriteLine(test.Message)
End Sub
End Class
End Namespace
--batch file to compile
%WINDIR%\Microsoft.NET\Framework\v3.5\csc.exe /target:library foo.cs
%WINDIR%\Microsoft.NET\Framework\v3.5\vbc.exe bar.vb /reference:foo.dll
--run bar.exe

- 8,658
- 2
- 33
- 35
-
3+1 for providing everything needed to run the test, even including the batch compilation command. Awesome. – keithwill Oct 29 '10 at 14:39
Managed assemblies (DLLs and EXEs) are not "C#" or "VB.NET" or any other language.
They are .NET assemblies with CIL and should interoperate with any .NET language.
Once you reference such an assembly in your project, you have access to all public types in it.
If you can't see any of the members, make sure they are indeed declared as public
, as C# will default to internal
or private
on most members.
Read more about access modifiers in C# here.

- 489,969
- 99
- 883
- 1,009
My guess is that the members you are trying to access are just not declared public
so they can't be used across namespaces.
If you want a working example, just create a new solution and follow below steps.
- Add a VB.net code project
- Add a public class.
- Add a C# Code project.
- Add a simple C# class.
When you have this setup, just make a project reference from one project to the other and try to call it in one of the created classes.
You can do this with any .Net dll as long as the members are declared public or the namespace is the same and the members are declared internal
.

- 14,221
- 15
- 70
- 110
Here is a working example - I had to rename some of your ComputeFingerprint
overloads in the C# code to get VB.Net to correctly recognize the specific one you want called. Perhaps these are the errors you would not resolve that you mentioned above?
C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace RF
{
/// <summary>
/// Génère des empreintes de fichiers
/// </summary>
public static class RabinFingerprint
{
/// <summary>
/// Bit 64 of the polynomial P is always 1 and not treated directly. This is the polynomial
/// with the leading coefficient removed (lcr).
/// Represents t^64 + t^4 + t^3 + t + 1.
/// </summary>
private static readonly UInt64 p_lcr = 0x000000000000001BL;
/// <summary>
/// It's not necessary to provide definitions for such integral constant variables as long as their
/// addresses are not taken.
/// Degree of the polynomial P.
/// </summary>
private static readonly int K = 64;
/// <summary>
/// Represents t^(K-1)
/// </summary>
private static readonly UInt64 T_K_minus_1 = (UInt64)1L << (K - 1);
/// <summary>
/// Broder's paper presents four pre-computed tables because words are considered to be 32-bit.
/// In this implementation W is a 64-bit integral type. Eight tables are used.
/// Table A is i1^127 + i2^126 + ... + i8^120.
/// Table B is i1^119 + i2^118 + ... + i8^112.
/// Table C, D, ..
/// Table E is i1^95 + i2^94 + ... + i8^88. (This is table A in the paper.)
/// Table F, G, H.
/// </summary>
private static UInt64[] tableA_ = new UInt64[256]; //Assuming byte size 8.
private static UInt64[] tableB_ = new UInt64[256];
private static UInt64[] tableC_ = new UInt64[256];
private static UInt64[] tableD_ = new UInt64[256];
private static UInt64[] tableE_ = new UInt64[256];
private static UInt64[] tableF_ = new UInt64[256];
private static UInt64[] tableG_ = new UInt64[256];
private static UInt64[] tableH_ = new UInt64[256];
/// <summary>
/// Constructor
/// </summary>
static RabinFingerprint()
{
InitTables();
}
/// <summary>
/// Initialize tables
/// </summary>
private static void InitTables()
{
//This represents t^(k + i) mod P, where i is the index of the array.
//It will be used to compute the tables.
UInt64[] mods = new UInt64[K];
//Remember t^k mod P is equivalent to p_lcr.
mods[0] = p_lcr;
for (int i = 1; i < K; ++i)
{
//By property: t^i mod P = t(t^(i - 1)) mod P.
mods[i] = mods[i - 1] << 1;
//If mods[i - 1] had a term at k-1, mods[i] would have had the term k, which is not represented.
//The term k would account for exactly one more division by P. Then, the effect is the same
//as adding p_lcr to the mod.
if ((mods[i - 1] & T_K_minus_1) != 0)
mods[i] ^= p_lcr;
}
//Compute tables. A control variable is used to indicate whether the current bit should be
//considered.
for (int i = 0; i < 256; ++i)
{
int control = i;
for (int j = 0; j < 8 && control > 0; ++j)
{
// bool.Parse(Convert.ToString())
if ((control & 1) == 1) //Ok, consider bit. ((byte))
{
tableA_[i] ^= mods[j + 56];
tableB_[i] ^= mods[j + 48];
tableC_[i] ^= mods[j + 40];
tableD_[i] ^= mods[j + 32];
tableE_[i] ^= mods[j + 24];
tableF_[i] ^= mods[j + 16];
tableG_[i] ^= mods[j + 8];
tableH_[i] ^= mods[j];
}
control >>= 1;
}
}
}
/// <summary>
/// Compute hash key
/// </summary>
/// <param name="value">Value to hash</param>
/// <returns>Value</returns>
private static UInt64 ComputeTablesSum(ref UInt64 value)
{
value = tableH_[((value) & 0xFF)] ^
tableG_[((value >> 8) & 0xFF)] ^
tableF_[((value >> 16) & 0xFF)] ^
tableE_[((value >> 24) & 0xFF)] ^
tableD_[((value >> 32) & 0xFF)] ^
tableC_[((value >> 40) & 0xFF)] ^
tableB_[((value >> 48) & 0xFF)] ^
tableA_[((value >> 56) & 0xFF)];
return value; //Pass by reference to return the same w. (Convenience and efficiency.)
}
/// <summary>
/// Compute hask hey
/// </summary>
/// <param name="HashArray">Array of Ulong bytes to ahsh</param>
/// <returns>Hash key</returns>
private static UInt64 Compute(UInt64[] HashArray)
{
UInt64 w = 0L;
for (int s = 0; s < HashArray.Length; ++s)
w = ComputeTablesSum(ref w) ^ HashArray[s];
return w;
}
/// <summary>
/// Compute the fingerprint
/// </summary>
/// <param name="source">String to compute</param>
/// <returns>Hash key</returns>
public static UInt64 ComputeFingerPrint(string source)
{
byte[] table = Encoding.Unicode.GetBytes(source);
UInt64[] values = new UInt64[table.LongLength];
ConvertBytes(ref table, ref values);
return Compute(values);
}
/// <summary>
/// Compute the fingerprint, you must use this method for very large text
/// </summary>
/// <param name="source">String to compute</param>
/// <returns>Hash key</returns>
public static UInt64 ComputeFingerPrint2(ref string source)
{
return ComputeFingerPrint(source);
}
/// <summary>
/// Compute the fingerprint, you must use this method for very large binary data
/// </summary>
/// <param name="source">Data to compute</param>
/// <returns>Hash key</returns>
public static UInt64 ComputeFingerPrint3(ref byte[] source)
{
UInt64[] values = new UInt64[source.LongLength];
ConvertBytes(ref source, ref values);
return Compute(values);
}
/// <summary>
/// Compute the fingerprint, you must use this method for very large binary data
/// </summary>
/// <param name="source">Data to compute</param>
/// <returns>Hash key</returns>
public static UInt64 ComputeFingerPrint4(byte[] source)
{
return ComputeFingerPrint3(ref source);
}
/// <summary>
/// Compute byte array to Uint64 array
/// </summary>
/// <param name="source">Table de byte source</param>
/// <param name="destination">Tableau de Uin64</param>
private static void ConvertBytes(ref byte[] source, ref UInt64[] destination)
{
for (long i = 0; i < source.LongLength; i++)
destination[i] = Convert.ToUInt64(source[i]);
}
}
}
VB.Net code (tested, result = 8533825001260623604):
Imports RF
Module Module1
Sub Main()
Dim input = "this is the string"
Dim result = RF.RabinFingerprint.ComputeFingerprint(input)
End Sub
End Module

- 53,498
- 9
- 91
- 140
-
Steve, thanks a lot for all your help. I wanted to let you know that the above code worked for me. I hope you don't mind I choose daddyman's answer as "the" answer for this question, although yours could have been it as well. – George Nov 01 '10 at 13:01
Would something like a C# to VB Converter work? If you have the code, and are comfortable with VB... work in VB.
This blog has an example of using C# as a class library in step 2. And a sample application.

- 2,137
- 6
- 31
- 51
-
I tried to convert it to VB but got some errors that I could not resolve. But please forget about that DLL, please give me a short example of something that actually works. From there I might be able to resolve my real issue. – George Oct 29 '10 at 14:36