I'm pretty sure this is a duplicate, but I've been unable to find a fix for this after a few hours of searching/trying.
I'm not an advanced programmer, but I have a decent amount of C++ experience. I'm trying to learn C# and having trouble with very basic syntax, especially for just accessing other classes. I've been looking for simple examples for a while, and overwhelmingly, everything I find seems to use one HUGE class, wherein the main method is used, so those examples haven't been very helpful.
I want to develop a solution with multiple .cs files (one class in each), and another .cs file containing the main method that I'll use for testing. My solution is named DIVAT. I have a Dealer.cs file with the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DIVAT
{
public class Dealer
{
public List<Tuple<int, string>> deck;
Dealer()
{ // default constructor
Console.Out.WriteLine("Default constructor called. (Dealer class)");
string [] suitValue = {"c", "d", "h", "s"};
for(int i = 2; i <= 14; i++){
for(int j = 0; j <= 3; j++){
deck.Add(new Tuple<int, string>(i, suitValue[j]));
}
}
}
~Dealer()
{// destructor
Console.Out.WriteLine("Destrcutor called. (Dealer class)");
}
Tuple<int, string> Dealer.getCard(int cardNum)
{// getter
return deck[cardNum];
}
}
}
Now I'm just trying to test this in another file, Program.cs. I'm hitting 2 bugs and can't figure out why. I am having a lot of trouble just trying to initialize my Dealer class. Also, I just want to test a getter function in my Dealer class.
I use to have a lot more static and private keywords throughout, but took those out as I was hitting bugs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DIVAT
{
class Program
{
static void Main(string[] args)
{
Dealer dealer = new Dealer();
// inaccessible due to it's protection level...
for (int i = 0; i <= 52; i++) {
Console.Out.WriteLine(dealer.getCard(i));
// does not contain a definition for getCard...
}
}
}
}
Sorry for such the basic questions, but I've been scouring the internet and trying different ways to fix this and have been unsuccessful. I feel like once I get past these few bugs, I should be able to convert a lot of my other code relatively painlessly.
Your constructor is implicitly private and since you provide zero public constructors, it cannot instantiate your class, even though the class itself is public..
You need to specify that it is public.
public Dealer() { }
As for your second question, you don't need to tell your methods that they belong to the class. They are already aware. Change your method signature like so:
public Tuple<int, string> GetCard(int cardNum)
{
// getter
return deck[cardNum];
}
Note that now the method is public and that we are scoped properly. In addition, note the PascalCasing on your method name. This is the appropriate naming convention for method names in C#.
Also, on another note, since C# is a managed language, you probably don't need your destructor.
Related
I'm trying to serialize/deserialize an IEnumerator generated from a function using yield.
I would like to serialize the IEnumerator at any iteration, I don't want to force it to generate all of it values.
I know that the yield keyword generate a class behind the scene, and that why I'm using it, to avoid manually writing iterator, and also to make the code cleaner.
My goal is to make a small game engine similar to Nick Gravelyn - The magic of yield, where each GameElement generate an iterator about his behavior, allowing the programmer to easily control timings (because the iterator allow to interrupt and continue a script). I want to try to add a multiplayer layer on top of that, that why I need to serialize/deserialize an IEnumerator.
Forcing the IEnumerator to generate all of his values also force the game to update, this should be avoided.
My first tentative was somethings like :
using System;
using System.Collections.Generic;
using System.Text.Json;
namespace SerializeTest
{
class Program
{
public static IEnumerator<int> CountTo(int end)
{
for(int i = 1; i <= end; i++)
{
Console.WriteLine("i = " + i);
yield return i;
}
}
static void Main(string[] args)
{
IEnumerator<int> e = CountTo(5);
string json = JsonSerializer.Serialize(e);
Console.WriteLine(json);
var f = JsonSerializer.Deserialize<IEnumerator<int>> (json); // crash because interface
while (f.MoveNext());
}
}
}
But deserializing an interface (IEnumerator<int>) is illegal, we need to know the Type of the object behind IEnumerator<int>.
Since the type is generated by the compiler, I try to use reflection over the Deserialize method in order to call it with the correct type generated by the function CountTo() (SerializeTest.Program+<CountTo>d__0 if you are curious)
So my second tentative was somethings like :
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.Json;
namespace SerializeTest
{
class Program
{
public static IEnumerator<int> CountTo(int end)
{
for(int i = 1; i <= end; i++)
{
Console.WriteLine("i = " + i);
yield return i;
}
}
public static T Deserialize<T>(string json) => JsonSerializer.Deserialize<T>(json); // still crash
static void Main(string[] args)
{
IEnumerator<int> e = CountTo(5);
string json = JsonSerializer.Serialize(e);
Console.WriteLine(json);
Type eType = e.GetType();
MethodInfo method = typeof(Program).GetMethod("Deserialize");
MethodInfo genericMethod = method.MakeGenericMethod(eType);
object fObj = genericMethod.Invoke(null, new object[] { json });
var f = (IEnumerator<int>)fObj;
while (f.MoveNext()) ;
}
}
}
but it still crash when calling JsonSerializer.Deserialize() even if the type is now correct and not an interface.
(System.InvalidOperationException : 'Each parameter in constructor 'Void .ctor(Int32)' on type 'SerializeTest.Program+<CountTo>d__0' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. The match can be case-insensitive.'
)
The format don't have any importance (json, xml...) as long as it is possible to send it to another computer and deserialize it back.
I naively hope that there is a way to Serialize/Deserialize an IEnumerator because a lot of cool stuff can be done with it, although I have some serious doubts about such a things to be possible.
Thank for reading so far.
I naively hope that there is a way to Serialize/Deserialize an IEnumerator because a lot of cool stuff can be done with it, although I have some serious doubts about such a things to be possible.
Sending code (and enumerator state machine generated by the compiler which you are trying to send is basically a code) is far more complex then just serializing it to json/xml/etc. For example Apache Ignite supports sending code to another nodes including assembly peer loading. One of the starting points for investigation can be here.
As for your attempt, as you should have already seen that serialized version of the state machine contains only one one property - Current: {"Current":0} while the generated class contains some other state data looking something like this:
private sealed class <<<Main>$>g__CountTo|0_0>d : IEnumerator<int>, IEnumerator, IDisposable
{
private int <>1__state;
private int <>2__current;
public int end;
private int <i>5__1;
int IEnumerator<int>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
// ... rest of the generated code
}
While you can look into writing your own custom converter that will use reflection to actually serialize/deserialize the internal state data (that is possibly not that hard), it can be quite brittle (class names can change, the generated code can change, the code generator code can change, and we have not even started with multiversion client support), in the end those fields a private for a reason, so I suggest looking into some set of messages the multiplayer clients will send to each other and you can turn them into iterators, classes, method calls, etc.
I'm currently writing a program in CLI/C++ using an imported C# package. I need to use one of the functions in one of the C# objects which takes in an array. Unfortunately it isn't allowing me to use a CLI array, defined like so:
array<float>^ knots = gcnew array<float>(nurbs->GetNumKnots());
(and then populated in a loop).
The object and the function are:
TRH::NURBSCurveKit^ nurbsKit = gcnew TRH::NURBSCurveKit();
nurbsKit->SetKnots(nurbs->GetNumKnots(), knots);
This returns an error basically saying that the cli::array type isn't compatible. Does anyone know of a way where I can cast the array, or possibly define it differently?
I'm quite new to CLI so I'm a little vague on the way it handles things at times.
Thanks
(I do something similar later on using an array of TRH::Points, but they're not defined as references or pointers, so I'm not sure if they'd work with any solutions or not).
I'm not sure if it's the same NURBSCurveKit, but according to an online API reference I found, the SetKnots method takes one parameter, not two. Since a managed array knows how long it is, you generally don't have to pass in a length with an array.
If this matches your API, just switch to pass a single parameter to SetKnots. (The reference I found uses a different namespace, so it may not be what you're using.)
array<float>^ knots = gcnew array<float>(nurbs->GetNumKnots());
TRH::NURBSCurveKit^ nurbsKit = gcnew TRH::NURBSCurveKit();
nurbsKit->SetKnots(knots);
This is my test case, seems everything is fine.
C#
namespace CS
{
public class Test
{
public int GetNum()
{
return 5;
}
public void ShowArray(int num, float[] arr)
{
for (int i = 0; i < num; i++)
{
Console.WriteLine("[{0}] = {1}",i,arr[i]);
}
}
}
}
C++/CLI
using namespace System;
using namespace CS;
int main(array<System::String ^> ^args)
{
Test^ test = gcnew Test();
array<float>^ arr = gcnew array<float>(test->GetNum());
for (int i = 0; i < test->GetNum(); i ++)
{
arr[i] = (float)i * i;
}
test->ShowArray(test->GetNum(), arr);
Console::ReadKey();
return 0;
}
Dose you code have something different form mine?
In my "LuaTest" namespace I have a class called "Planet". The C# code reads like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LuaInterface;
namespace LuaTest
{
public class Planet
{
public Planet(string name)
{
this.Name = name;
}
public Planet() : this("NoName") { }
public string Name
{
get;
private set;
}
public void printName()
{
Console.WriteLine("This planet's name is {0}", Name);
}
}
}
Then I built LuaTest.dll and copied this file to the same folder where my Lua script is saved. In the Lua script I wrote:
--define Path for required dlls
package.cpath = package.cpath .. ";" .. "/?.dll"
package.path = package.path .. ";" .. "/?.dll/"
require 'luanet'
luanet.load_assembly("LuaTest")
local Planet = luanet.import_type("LuaTest.Planet")
local planet = Planet("Earth")
planet.printName()
However, this piece of code does not work. Lua interpreter throws this error:
lua: dllTest.lua:7: attempt to call local 'Planet' (a nil value)
I suspect that my LuaTest assembly is not loaded at all. Could anyone point out where I did wrong? I would very much appreciate it, since I've been stuck by this problem for days.
Also it might be helpful to add that my LuaInterface.dll is the rebuilt version in .NET4.0 environment.
So I spent a LOT of time similarly. What really drove me bonkers was trying to get Enums working. Eventually I ditched my project for a very simplified console application, very similar (ironically also named 'LuaTest').
Edit: I've noted that the initial "luanet.load_assembly("LuaTest")" appears superfluous. Works with it, or surprisingly without it.
Another Edit: As in my badly edited comment below, when I removed:
print(luanet.LuaTest.Pointless)
It all stopped working (LuaTest.Pointless became nil). But adding the luanet.load_assembly("LuaTest") then makes it work. It may be that there is some sort of odd implicit load in the print or in just expressing they type. Very Strange(tm).
In any case, it seems to work for me (note: after a lot of experimentation). I don't know why yours is failing, I don't note any real difference, but here's all my code in case someone else can spot the critical difference:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LuaInterface;
namespace LuaTest
{
public class Program
{
static void Main(string[] args)
{
Lua lua = new Lua();
lua.DoFile("test.lua");
}
public int some_member = 3;
}
public class Pointless
{
public enum AnEnum
{
One,
Two,
Three
};
public static string aStaticInt = "This is static.";
public double i;
public string n = "Nice";
public AnEnum oneEnumVal = AnEnum.One;
private AnEnum twoEnumVal = AnEnum.Two;
private string very;
public Pointless(string HowPointLess)
{
i = 3.13;
very = HowPointLess;
}
public class MoreInnerClass
{
public string message = "More, please!";
}
public void Compare(AnEnum inputEnum)
{
if (inputEnum == AnEnum.Three)
Console.WriteLine("Match.");
else
Console.WriteLine("Fail match.");
}
}
}
and test.lua:
luanet.load_assembly("LuaTest")
--Pointless is a class in LuaTest assembly
local Pointless = luanet.import_type("LuaTest.Pointless")
print(Pointless)
--Gives 'ProxyType(LuaTest.Pointless): 46104728
print(Pointless.aStaticInt)
--'This is static.'
--Fails if not static, as we expect
--Instantiate a 'Pointless'.
local p = Pointless("Very")
print(p)
--Gives 'LuaTest.Pointless: 12289376'
--Now we can get at the items inside the Pointless
--class (well, this instance, anyway).
local e = p.AnEnum;
print(e)
--ProxyType(LuaTest.Pointless+AnEnum): 23452342
--I guess the + must designate that it is a type?
print(p.i)
--3.14
print(p.oneEnumVal)
--Gives 'One: 0'
print(p.twoEnumVal)
--Gives 'twoEnumVal'... private
--behaves very differently.
print(e.Two:ToString())
--Gives 'Two'
local more = p.MoreInnerClass()
print(more.message)
--'More, Please!'
--create an enum value here in the script,
--pass it back for a comparison to
--the enum.
local anotherEnumVal = p.AnEnum.Three
p:Compare(anotherEnumVal)
--outputs 'Match'
Having spent the last several days working on a project that required this exact functionality from LuaInterface, I stumbled across a piece of Lua code that turned out to be the perfect solution (see Reference 1). Whilst searching for this solution, I noticed this question and figured I'd drop my two cents in.
To apply this solution, I merely run the CLRPackage code while initializing my LuaInterface Lua object. However, the require statement works just as well.
The code provided in reference 1 allows the use of import statements, similar to C# using statements. Once an assembly is imported, its members are accessible in the global namespace. The import statement eliminates the need to use load_assembly or import_type (except in situations in which you need to use members of the same name from different assemblies. In this scenario, import_type would be used similar to C# using NewTypeName = Assembly.OldTypeName).
import "LuaTest"
planet = Planet("Earth")
planet:printName()
This package also works great with enums!
Further information regarding the use of this package may be found at Reference 2.
Hope this helps!
Reference 1: https://github.com/stevedonovan/MonoLuaInterface/blob/master/bin/lua/CLRPackage.lua
Reference 2: http://penlight.luaforge.net/project-pages/penlight/packages/LuaInterface/
I spent some time in binding C# dll to lua. Your posts were helpful but something was missing. The following solution should work:
(Make sure to change your compiler to .NET Framework 3.5 or lower!)
Planet.dll:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Planets
{
public class Planet
{
private string name;
public string Name
{
get { return name; }
set { this.name = value; }
}
private float diameter;
public float Diameter
{
get { return diameter; }
set { this.diameter = value; }
}
private int cntContinents;
public int CntContinents
{
get { return cntContinents; }
set { this.cntContinents = value; }
}
public Planet()
{
Console.WriteLine("Constructor 1");
this.name = "nameless";
this.diameter = 0;
this.cntContinents = 0;
}
public Planet(string n, float d, int k)
{
Console.WriteLine("Constructor 2");
this.name = n;
this.diameter = d;
this.cntContinents = k;
}
public void testMethod()
{
Console.WriteLine("This is a Test!");
}
}
}
Use the code above, paste it into your class library project and compile it with .NET smaller or equal 3.5.
The location of the generated DLL needs to be known by the lua enviroment. Paste it e.g at "clibs"-folder or another well known lua system path. Then try to use the following lua example. It should work.
Test1.lua: (Option 1 with "import" from CLRPackage)
require "luanet"
require "CLRPackage"
import "Planet"
local PlanetClass = luanet.import_type("Planets.Planet")
print(PlanetClass)
local PlanetObject1 = PlanetClass()
print(PlanetObject1)
local PlanetObject2 = PlanetClass("Earth",6371.00*2,7)
print(PlanetObject1.Name)
PlanetObject1.Name = 'Mars'
print(PlanetObject1.Name)
print( "Planet " ..
PlanetObject2.Name ..
" is my home planet. Its diameter is round about " ..
PlanetObject2.Diameter .. "km." ..
" Our neighour is " ..
PlanetObject1.Name)
Test2.lua: (Option 2 with "load_assembly")
require "luanet"
require "CLRPackage"
luanet.load_assembly("Planet")
local PlanetClass = luanet.import_type("Planets.Planet")
print(PlanetClass)
local PlanetObject1 = PlanetClass()
print(PlanetObject1)
local PlanetObject2 = PlanetClass("Earth",6371.00*2,7)
print(PlanetObject1.Name)
PlanetObject1.Name = 'Mars'
print(PlanetObject1.Name)
print( "Planet " ..
PlanetObject2.Name ..
" is my home planet. Its diameter is round about " ..
PlanetObject2.Diameter .. "km." ..
" Our neighour is " ..
PlanetObject1.Name)
In both cases the console output will look like this:
ProxyType(Planets.Planet): 18643596
Constructor 1
Planets.Planet: 33574638
Constructor 2
nameless
Mars
Planet Earth is my home planet. Its diameter is round about 12742km. Our neighbour is Mars
I hope its helps some of you.
Edit 1:
by the way, a method call from lua looks like this:
PlanetObject1:testMethod()
PlanetObject2:testMethod()
Edit 2:
I found different dll's whitch needed to be handled differently. One needed the "import"-function and another needed the "load_assembly"-function. Keep that maybe in mind!
OK, I am mostly a LAMP developer so I am new to the entity framework. However, I am familiar with the basics in LINQ and have generated a entity model from my DB. Now here is my requirement:
I have a datagrid on a WinForm that will be refreshed from a data source on a remote server every few seconds as changes to the dataset are made from other sources. Obviously, I'd like to construct a lambda expression to get the right anonymous type to satisfy the columns that needs to be shown in my datagrid. I have done this and here is the result (I'm using a custom datagrid control, btw):
And my code thus far:
Models.dataEntities objDB = new Models.dataEntities();
var vans = from v in objDB.vans
select v;
gcVans.DataSource = vans;
OK, so now I have my basic data set. One problem I had is that the "Status" column will show a calculated string based on several parameters in the data set. I added this to my entities via a partial class. As you can see in the screenshot, this is working correctly:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WindowsFormsApplication1.Models {
public partial class van {
public string van_status {
get {
if (this.is_offline == 1) {
return "Offline";
} else if (this.is_prayer_room == 1) {
return "In Prayer Room";
} else {
return "TODO: Create statuses";
}
}
}
}
}
This added property works fine. However, the second I try to project the status in an anonymous type so I can also retrieve the school name, I get an error:
Models.dataEntities objDB = new Models.dataEntities();
var vans = from v in objDB.vans
select new {
van_name = v.van_name,
school_name = v.school.school_name,
capacity = v.capacity,
phone = v.phone,
van_status = v.van_status
};
gcVans.DataSource = vans;
So, I have two questions:
1) If I cannot use computed properties of my partial classes in LINQ projections, how am I supposed to show my computed string in my datagrid?
2) Am I even approaching this correctly? When I resolve #1, how would I refresh this data (ie during a timer fire event)? Would I simply call objDB.refresh() and then tell my datagrid to update from the datasource? Does calling that method actually run the lambda expression above or does it load everything from the DB?
Thanks for any assistance with this. Also, if you have any best practices to share that would be awesome! I hope I explained this as thoroughly as you need to provide assistance.
1) Instead of modifying your EF object with a partial class you could always create your own class that contains your read only property van_status. The code you've got would be nearly identical:
Models.dataEntities objDB = new Models.dataEntities();
gcVans.DataSource = from v in objDB.vans
select new DisplayVan {
van_name = v.van_name,
school_name = v.school.school_name,
capacity = v.capacity,
phone = v.phone,
};
The van_status property, since it's read-only, will not need to be specified in the query.
2) I'm more a web developer than a desktop developer so I'll give you my take on how to refresh the grid (it may not be the preferred methodology for fat clients)...
I'm reluctant to trust .Refresh() methods and hope all works to maximal efficiency and work properly. Instead, encapsulate the code from #1 in a method of your own and invoke it from your timer event firing (or however you choose to implement the periodic refresh).
Another good option would be to create an extension method.
Here is a simple example:
using System;
namespace WindowsFormsApplication1 {
static class Program {
[STAThread]
static void Main() {
Van van = new Van();
string status = van.GetStatus();
}
}
public static class VanExtension {
public static string GetStatus(this Van van) {
if(van.is_offline == 1) {
return "Offline";
}
else if(van.is_prayer_room == 1) {
return "In Prayer Room";
}
return "TODO: Create statuses";
}
}
public class Van {
public int is_offline { get; set; }
public int is_prayer_room { get; set; }
}
}
Be sure to put this extension class in the same namespace as the entity class.
I need some advice on how to do the following in either C# and VB.net.
In C++, in my header file I do the following:
#define StartButtonPressed Input[0]==1 // Input is an array declared in .cpp file
In my .cpp file, i have a code something like this:
if(StartButtonPressed)
// do something
The reason of me doing so is so that my code is easier to read.
I tried the same thing in C# but it got error. How could I do the same thing in C# and VB.Net?
Please advice. Thanks.
There is no good reason to use a macro for this in C++; you could just as easily make it a function and the code would be far cleaner:
bool IsStartButtonPressed()
{
return Input[0] == 1;
}
Input should also probably be passed as an argument to the function, but it's hard to tell exactly where that is coming from.
You're best off creating a property in your class
protected bool StartButtonPressed {
get { return Input[0] == 1; }
}
then your code can be as before
.
.
.
if(StartButtonPressed) {
.
.
.
}
However for consistency with the .net framework I'd suggest calling the property IsStartButtonPressed
If you need to to be evaluated at the point of the if statement then you really need a function or a property. However is this is one time evaluation you can use a field
bool isStartButtonPressed = Input[0] ==1;
If you want may classes to have this functionality then I'd recommend a static function from another class, something like
public static class ButtonChecker {
public static bool IsPressed(int[] input) {
return input[0] == 1;
}
}
Then you call it anywhere with
if(ButtonChecker.IsPressed(Input)) {
.
.
}
But ultimately you cannot use macro's like you're used in C/C++. You shouldn't be worried about performance of properties and functions like this as the CLR jit compiler implementation is very very good for them
Here is an example program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace ConsoleApplication1 {
public static class ButtonChecker {
public static bool IsPressed(int[] input) {
return input[0] == 1;
}
}
static class Program {
public static void Main(){
int[] Input = new int[6] { 1, 0, 2, 3,4 , 1 };
for(int i = 0; i < Input.Length; ++i){
Console.WriteLine("{0} Is Pressed = {1}", i, ButtonChecker.IsPressed(Input));
}
Console.ReadKey();
}
}
}
You could use an enum
public enum buttonCode
{
startButton = 0,
stopButton = 1
// more button definitions
}
Then maybe one function
public bool IsButtonPressed(b as buttoncode)
{
return Input[b] == 1;
}
Then your calls look like:
if IsButtonPressed(buttonCode.StartButton) { }
The only changes needed to switch button codes are then in the enum, not spread across multiple functions.
Edited to Add:
If you want individually named functions, you could do this:
public bool IsStartButtonPressed()
{
return Input[buttonCode.StartButton] == 1;
}
Still, all of the edits would be in the enum, not the functions.
Bjarne Stroustrup wrote:
The first rule about macros is: Do not use them if you do not have to. Almost every macro demonstrates a flaw in the programming language, in the program, or in the programmer.
It's worth noting two things here before saying anything else. The first is that "macro" can mean a very different thing in some other languages; one would not make the same statement about Lisp. the second is that Stroustrup is willing to take his share of the blame in saying that one reason for using macros is "a flaw in the programming language", so it's not like he's just being superior in condemning their use.
This case though isn't a flaw in the programming language, except that the language lets you do it in the first place (but has to, to allow other macros). The only purpose of this macro is to make the code harder to read. Just get rid of it. Replace it with some actual C# code like:
private bool StartButtonPressed
{
get
{
return Input[0]==1
}
}
Edit:
Seeing the comment above about wanting to be faster to code, I would do something like:
private enum Buttons
{
Start = 0,
Stop = 1,
Pause = 2,
/* ... */
}
private bool IsPressed(Buttons button)
{
return Input[(int)button] == 1;
}
And then call e.g. IsPressed(Buttons.Start). Then I'd fix the C++ to use the same approach too (in C++ I would even be able to leave out the Buttons. where I wanting particularly great concision).