|
Thanks Luc. If you say it's complex, then it must be too far for me to grasp.
I've decided to use the IClientFormHelper class as an extension method call, that I will just have to repeat in my IClientForm window classes.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Hm. The one link shows there are many aspects to the default implementation inside interfaces, that article is hard to read and understand in one go.
The first answer in the SO link shows how a default property getter could be written; that is simple, and at first glance what you want could be implemented likewise as a default setter.
Luc Pattyn [My Articles]
The Windows 11 taskbar is a disgrace; a third-party add-on is needed to reverse the deterioration. I decline such a downgrade.
|
|
|
|
|
That's one of the major things that stumped me. Since an interface can't contain data members, then if I try to write a default setter, I have nothing to assign it to.
It was at that point that I gave up!
EDIT:
Maybe I should solve the problem by using the inheritance of a base class, rather than trying to stuff it into the interface.
That gives me an idea...
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
You could use properties rather than variables, couldn't you? That is what the example does...
Luc Pattyn [My Articles]
The Windows 11 taskbar is a disgrace; a third-party add-on is needed to reverse the deterioration. I decline such a downgrade.
|
|
|
|
|
Yes I could use properties, but at some point in the call stack, the value must be assigned to a data member in the window instance.
So that's code that must be repeated in each class, unless I derive from a base class.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
|
Richard Andrew x64 wrote: default method in an interface works.
Default interface methods - C# feature specifications | Microsoft Learn[^]
"to add methods to an interface in future versions without breaking source or binary compatibility with existing implementations of that interface."
The feature is a hack which should be avoided if possible.
It does not fit your case. An abstract class is a better starting point for your example.
|
|
|
|
|
Thanks for your advice.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
I may not understand fully, but perhaps something like this?
public interface IMyInterface
{
static IMyInterface Instance = new MyStruct();
int Number { get; set; }
}
record struct MyStruct(int Number) : IMyInterface
{
}
Then you can use it like this
public void DoWork()
{
IMyInterface myInterface = IMyInterface.Instance;
myInterface.Number = 500;
Console.WriteLine(myInterface.Number);
}
|
|
|
|
|
There different types of interface in C#.
One is the IInterface , which is like the "interface is a contract" idea.
class Foo : IBar{}
Another is the "Port Interface"
class Foo {
private int FooData1, FooData2;
public interface Port {
public const String Name = "";
public static ValueType Action(){
return (FooData1, FooData2);
}
}
}
In the second case the interface is basically a lightweight static class (it even has constructors).
Default implementations fall in between, sort of. Default implementations are like virtual methods.
If you realize an IInterface that has default implementation and do not realize the operation, it will do something similar to the second case. But it places the method on the object and not on an inner interface. If the operation is realized it's like an auto-override of the default virtual implementation.
Another difference is that the default implementation methods are instance and the interface methods are static.
|
|
|
|
|
It may be worth pointing out that as the code stands Port interface has no access to FooData1 or FooData2.
public class Foo : Foo.Port
{
private Foo() { }
public int FooData1 { get; set; }
public int FooData2 { get; set; }
public interface Port
{
static Port Default = new Foo();
protected int FooData1 { get; }
protected int FooData2 { get; }
static (int, int) Action()
{
return (Default.FooData1, Default.FooData2);
}
}
}
Now we have access to FooData1 and FooData2. Foo is private and the only instance of Foo or Port is Foo.Port.Default and we can access it as such.
var bar = Foo.Port.Default;
var foobar = (Foo)bar;
foobar.FooData1 = 10;
foobar.FooData2 = 20;
Console.WriteLine(Foo.Port.Action());
If we want more than the single instance of Foo we need a Clone() method in Foo which can be easily done like this.
public object Clone()
{
var (X, Y) = Foo.Port.Action();
return new Foo()
{
FooData1 = X,
FooData2 = Y
};
}
modified 7-Oct-24 13:13pm.
|
|
|
|
|
Console.WriteLine doesn't write to the debugger Output window in .NET 8.
It always works in the .NET Framework, but not in the new .NET.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
|
Ah! Makes sense. Thanks!
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Hi
I need to make a game using window form in c#
just an example
thx.
|
|
|
|
|
|
While we are more than willing to help those that are stuck, that doesn't mean that we are here to do it all for you! We can't do all the work, you are either getting paid for this, or it's part of your grades and it wouldn't be at all fair for us to do it all for you.
So we need you to do the work, and we will help you when you get stuck. That doesn't mean we will give you a step by step solution you can hand in!
Start by explaining where you are at the moment, and what the next step in the process is. Then tell us what you have tried to get that next step working, and what happened when you did.
Just saying "I wanna write a game" doesn't help anyone!
If you are having problems getting started at all, then this may help: How to Write Code to Solve a Problem, A Beginner's Guide[^]
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
bool playing = true;
public Form1()
{
InitializeComponent();
}
private Button[] Cells => new Button[]
{
button1,
button2,
button3,
button4,
button5,
button6,
button7,
button8,
button9
};
private bool IsBoardFull
{
get
{
bool result = true;
foreach (Button btn in Cells)
{
if (btn.Enabled) { result = false; break; }
}
return result;
}
}
private bool IsThreeInRow
{
get
{
if (Cells[0].Text == "X" && Cells[1].Text == "X" && Cells[2].Text == "X" ||
Cells[0].Text == "O" && Cells[1].Text == "O" && Cells[2].Text == "O" ||
Cells[3].Text == "X" && Cells[4].Text == "X" && Cells[5].Text == "X" ||
Cells[3].Text == "O" && Cells[4].Text == "O" && Cells[5].Text == "O" ||
Cells[6].Text == "X" && Cells[7].Text == "X" && Cells[8].Text == "X" ||
Cells[6].Text == "O" && Cells[7].Text == "O" && Cells[8].Text == "O" ||
Cells[0].Text == "X" && Cells[3].Text == "X" && Cells[6].Text == "X" ||
Cells[0].Text == "O" && Cells[3].Text == "O" && Cells[6].Text == "O" ||
Cells[1].Text == "X" && Cells[4].Text == "X" && Cells[7].Text == "X" ||
Cells[1].Text == "O" && Cells[4].Text == "O" && Cells[7].Text == "O" ||
Cells[2].Text == "X" && Cells[5].Text == "X" && Cells[8].Text == "X" ||
Cells[2].Text == "O" && Cells[5].Text == "O" && Cells[8].Text == "O" ||
Cells[0].Text == "X" && Cells[4].Text == "X" && Cells[8].Text == "X" ||
Cells[0].Text == "O" && Cells[4].Text == "O" && Cells[8].Text == "O" ||
Cells[2].Text == "X" && Cells[4].Text == "X" && Cells[6].Text == "X" ||
Cells[2].Text == "O" && Cells[4].Text == "O" && Cells[6].Text == "O")
return true;
return false;
}
}
private IEnumerable<Button> PossibleMoves()
{
return Cells.Where((button) => button.Enabled);
}
private void CheckForWinner()
{
string draw = "Sorry, it was a draw.";
string playAgain = "Another Game?";
string sorry = "Sorry, you lost.";
string congrats = "Congratulations, you won.";
if(IsThreeInRow)
{
string state = playing ? congrats : sorry;
DialogResult dialogResult = MessageBox.Show(
state, playAgain, MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
ResetGame();
return;
}
Close();
}
else if(IsBoardFull)
{
DialogResult dialogResult = MessageBox.Show(
draw, playAgain, MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
ResetGame();
return;
}
Close();
}
}
private void Cell_Click(object sender, EventArgs e)
{
if (!playing) return;
Button btn = (Button)sender;
if(string.IsNullOrEmpty(btn.Text))
{
PerformMove(btn);
return;
}
}
private void PerformMove(Button btn)
{
if(playing)
{
btn.Text = "X";
btn.Enabled = false;
CheckForWinner();
playing = false;
ComputerPlay();
return;
}
btn.Text = "O";
btn.Enabled = false;
CheckForWinner();
playing = true;
}
private void ResetGame()
{
foreach(Button btn in Cells)
{
btn.Text = null;
btn.Enabled = true;
}
}
private void ComputerPlay()
{
if (playing) return;
var possibleMoves = PossibleMoves();
int index = new Random((int)DateTime.Now.
Ticks).Next(0, possibleMoves.Count());
Button btn = possibleMoves.ElementAt(index);
PerformMove(btn);
}
|
|
|
|
|
How do I check for existance or clear the contents of a SharePoint List from C# code?
I have complete the code that creates a sharepoint List from scratch, creates the columns, and loads the data that I get from an API GET query of an external database.
How do I:
check and see if the SharePoint List already exists
clear the contents of the sharepoint list
load the list with new data.
Without doing these steps, I am left with creating the list from scratch each time and giving it a unique name each time.
Is there some source of information on how to do this that I can find online? The Microsoft AI chat bot has given me some code that does not work at all.
|
|
|
|
|
|
Hi Charles,
I sure can. Editing it or presenting it in such a way where company information is no there is going to take time. The code first assumes it is creating the list for the first time and when an exception is thrown if the list already exists, it just loads the list. Here is the code
string listTitle = "TripLegs" ;
string listDescription = "This is a new list created using CSOM";
Microsoft.SharePoint.Client.List? newList = null;
Next, we use the "using" method and start a block like this:
using (var authenticationManager = new AuthenticationManager())
using (var context = authenticationManager.GetContext(site, user, password))
{
context.Load(context.Web, p => p.Title);
await context.ExecuteQueryAsync();
Console.WriteLine($"Title: {context.Web.Title}");
Web web = context.Web;
ListCreationInformation creationInfo = new ListCreationInformation();
creationInfo.Title = listTitle;
creationInfo.Description = listDescription;
creationInfo.TemplateType = (int)ListTemplateType.GenericList;
newList = web.Lists.Add(creationInfo);
THis is when the try catch block is used if an exception is NOT thrown, then we assume that we are dealing with a list that has not been created yet and the use of the ListCreationInformation class is the proper thing to do. The code in the "TRY" block proceeds to create the columns.
try
{
context.Load(newList);
context.ExecuteQuery();
Console.WriteLine("List created successfully!");
FieldCollection fields = newList.Fields;
#region ColumnHeaders
<pre> FieldCreationInformation fieldInfo_1 = new FieldCreationInformation(FieldType.Number)
{
DisplayName = "TripId",
InternalName = "TripId",
Group = "Custom Columns",
AddToDefaultView = true
};
string fieldSchema_1 = $"<Field Type='{fieldInfo_1.FieldType}' Name='{fieldInfo_1.InternalName}' DisplayName='{fieldInfo_1.DisplayName}' Group='{fieldInfo_1.Group}' />";
Field Field_1 = newList.Fields.AddFieldAsXml(fieldSchema_1, true, AddFieldOptions.DefaultValue);
Field_1.Update();
context.ExecuteQuery();
then the code generates all the columns. The example I just posted shows the creation of just the first column.
So, now we get to the Catch block which would be executed if the list already exists and we just need to access it in order to load the already existing list
}
catch (Exception ex)
{
After this is some JSON code that deals with the parsing of the code to put in the list which I am intentionally leaving out. But the code is put into a class and then from the class, it is loaded into the Sharepoint List like this:
Legs singleTripLeg = JsonSerializer.Deserialize<Legs>(inputLegsJSON);
ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
Microsoft.SharePoint.Client.ListItem newItem = newList.AddItem(itemCreateInfo);
newItem["TripId"] = singleTripLeg.TripId;
newItem["ExternalReference"] = singleTripLeg.ExternalReference;
newItem["DepartureAirportId"] = singleTripLeg.DepartureAirportId;
newItem["ArrivalAirportId"] = singleTripLeg.ArrivalAirportId;
newItem["LandedLocal"] = singleTripLeg.LandedLocal;
newItem["LandedPinned"] = singleTripLeg.LandedPinned;
newItem.Update();
context.ExecuteQuery();
So there you have it.
Now I need to know the call to clear out the SharePoint List before I load it.
|
|
|
|
|
|
using locks, from my understanding this should work as long as lock is being called on the same object.
internal static async Task Lock<T>(this T lockObject, Action DoAction) where T : class
{
await Task.Run(() => { lock(lockObject)
{
DoAction();
}});
}
|
|
|
|
|
From what I can see, the code you've provided isn't going to achieve what you might expect it to achieve. I'm going to break the logic down so you can see where the confusion lies.- The await operator here does not appear to affect the locking behaviour. It's only waiting for the Task.Run to complete.
- Inside the
Task.Run , we have a lock statement. You can think of this as running on a different thread from the caller. - Each call to this method will create a new task, which will attempt to acquire the lock independently.
The end result is multiple calls to this method could run concurrently, each in its own task, defeating the purpose of the lock. The lock will still work within each individual task, but it won't prevent multiple tasks from running simultaneously. To my mind, a better version of this would be this:
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
internal static async Task Lock<T>(this T lockObject, Action DoAction) where T : class
{
try
{
await _semaphore.WaitAsync();
DoAction();
}
finally
{
_semaphore.Release();
}
}
|
|
|
|
|
Thanks for the hint on the using the SemaphoreSlim. This works much better than the original extension I was using.
|
|
|
|