|
using C# 8 new Interface features:
public interface IExampleInterface
{
void DefaultMethod()
{
Console.WriteLine("This is the default implementation of DefaultMethod.");
}
static void StaticMethod()
{
Console.WriteLine("This is a static method in an interface.");
}
} And ... in C#9: Init-only setters; Target-typed new expressions ... in C#10: Record structs.
imho, Interface is becoming very different, and learning the strategic use of the new features much more difficult.
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
I agree with your final statement. I would be interested in knowing what new devs, coming to .NET now, think of it.
|
|
|
|
|
Just to make things more confusing, a static interface member with a default implementation must be marked as virtual , otherwise you'll get a compiler error when you try to use it:
public interface IFoo
{
static void S() => Console.WriteLine("Default");
}
static void Test<T>() where T : IFoo
{
T.S();
} If you don't provide a default implementation, you have to mark it as abstract .
In order to provide its own implementation, a class has to declare the method as public , which doesn't match the interface declaration, leading to more confusion:
public interface IFoo
{
static virtual void S() => Console.WriteLine("Default");
}
public class Foo : IFoo
{
static void S() => Console.WriteLine("Overridden");
}
static void Test<T>() where T : IFoo
{
T.S();
}
Test<Foo>(); You can alleviate that by marking the interface method as public :
public interface IFoo
{
public static virtual void S() => Console.WriteLine("Default");
} But IMO, adding access modifiers to interface members goes against the "ethos" of interfaces. If I can see the interface, then I should be able to access all members of that interface, so they shouldn't need to be marked as public . And having some members protected or private just seems like nonsense!
And if that's still not confusing enough, the implementation of the static method cannot use the override modifier, even though it's required when you provide an implementation of a virtual / abstract method from a base class:
public class Foo : IFoo
{
public static override void StaticMethod() => Console.WriteLine("Overridden");
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Richard Deeming wrote: adding access modifiers to interface members goes against the "ethos" of interfaces. "ethos" ... right word !
i am curious which versions of future C#/.NET your thorough review of future "features" are based on ...
aside: i am still hung-up on the fact that C# inner classes within outer classes "mean nothing" ... unless, of course you want to make them private and only use/manipulate then from within their containing classes ... i am probably still in recovery from 'Self in SmallTalk, "super" in Java ... my problem !
cheers, bill
`
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
|
Some more confusion for you from Reddit, relating to the older default interface implementation rather than the newer static interface members:
I had a question while reading the Microsoft docs on interfaces
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods#reabstraction[^]
In the docs, they give the example
interface IA
{
void M() { WriteLine("IA.M"); }
}
interface IB : IA
{
abstract void IA.M();
}
class C : IB { }
Which forces you to implement method M in class C . However, you can also define the interface IB this way, which also forces method M to be defined in class C .
interface IA
{
void M() { WriteLine("IA.M"); }
}
interface IB : IA
{
new void M();
}
class C : IB { }
I did notice there is a small difference, where since in the second example, interface IB is shadowing IA, the error message changes, but in practice, is there any difference between these two?
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I would prefer the second one as it completely hides IA from C (which mostly I would want when I setting up like this). This also suggests me that the 1st implementation is for scenarios where you don't want to hide and be much more explicit about who is asking to implement (also IB is mostly playing middlemen for some reason known/unknown).
|
|
|
|
|
I'm populating a Datagriview from a text file with several lines with 15 numbers each, these numbers change every day, as well as the number of lines.
Ex:
*01 05 08 09 10 12 15 16 17 18 19 20 22 24 25
*02 07 08 09 10 11 15 16 17 18 20 21 22 24 25
*01 07 08 09 10 12 13 15 17 18 19 20 21 22 25
I also have an array that generates 15 random numbers between 01 and 25,
ex: 01 02 04 05 08 09 13 15 16 17 18 19 20 22 25
I need to count how many numbers in each line are repeated with the numbers in the array.
tenho seguinte codigo, mas não me traz um resultado satisfatório.
<pre> private IDictionary<int, int> GetResultFromTextFile(IEnumerable<int> src)
{
var filePath = @"C:\BoaSorte\Banco\testeResultado.txt";
var delimiter = new[] { ' ' };
var dict = File.ReadLines(filePath)
.Where(line => !string.IsNullOrEmpty(line))
.Aggregate(new Dictionary<int, int>(), (d, line) =>
{
var values = line
.Split(delimiter, StringSplitOptions.RemoveEmptyEntries)
.Select(x => int.Parse(x));
var matchCount = values.Where(v => src.Contains(v)).Count();
if (matchCount <= 15)
{
if (d.ContainsKey(matchCount))
d[matchCount]++;
else
d[matchCount] = matchCount;
}
return d;
});
return dict;
}
<pre>private void button1_Click(object sender, EventArgs e)
{
int outVal;
if (UltimoResultado.Any(Acertos => !int.TryParse(Acertos.Text, out outVal)))
{
MessageBox.Show("Valores Invalidos...");
return;
}
var arr = UltimoResultado.Select(linha => int.Parse(linha.Text));
var result = GetResultFromTextFile(arr).ToList();
for (int i = 0; i < result.Count; i++)
{
dgHits.Rows[i].Cells["Acertos"].Value = result[i].ToString();
}
}
a picture of how i'm receiving
how am i receiving
how do i need it to appear
thank you in advance for any comments
modified 20-Aug-23 23:06pm.
|
|
|
|
|
And?
What have you tried?
Where are you stuck?
What help do you need?
"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!
|
|
|
|
|
Your code is storing the repeated counts as keys in the dictionary, which results in multiple repetitions being displayed in a single row in the DataGridView in your 'Acertos' cell.
You need to store the dictionary values to store the count of repetitions for each line, rather than the repeated count itself -
private IDictionary<int, int> GetResultFromTextFile(IEnumerable<int> src)
{
var filePath = @"C:\BoaSorte\Banco\testeResultado.txt";
var delimiter = new[] { ' ' };
var dict = File.ReadLines(filePath)
.Where(line => !string.IsNullOrEmpty(line))
.Aggregate(new Dictionary<int, int>(), (d, line) =>
{
var values = line
.Split(delimiter, StringSplitOptions.RemoveEmptyEntries)
.Select(x => int.Parse(x));
var matchCount = values.Count(v => src.Contains(v));
if (d.ContainsKey(matchCount))
d[matchCount]++;
else
d[matchCount] = 1;
return d;
});
return dict;
}
private void button1_Click(object sender, EventArgs e)
{
int outVal;
if (UltimoResultado.Any(Acertos => !int.TryParse(Acertos.Text, out outVal)))
{
MessageBox.Show("Valores Invalidos...");
return;
}
var arr = UltimoResultado.Select(linha => int.Parse(linha.Text));
var result = GetResultFromTextFile(arr).ToList();
for (int i = 0; i < result.Count; i++)
{
dgHits.Rows[i].Cells["Acertos"].Value = result[i].Value.ToString();
}
}
|
|
|
|
|
hello André Oosthuizen, Muito Obrigado por responder meu tópico.
what is happening to me is that it returns the repeated numbers of the Array [ex: 13 hits, and the number of lines with 13 hits ex: 2]
I would like only the Hits to return, each one in its respective line as in the second image,
this code is returning the amount of line as n Hits,
if (d.ContainsKey(matchCount))
d[matchCount]++;
else
d[matchCount] = 1;
I need the opposite, the number of hits for each line (or Repeated from the array)
it's working, but the lines that have the same number of hits don't return anything
<pre lang="C#">if (matchCount <= 15) { d[matchCount] = matchCount; }
modified 9-Aug-23 21:14pm.
|
|
|
|
|
I think I know what you need, try the following code. I did not test it so you might need to change it to do exactly as you require -
private IDictionary<int, int> GetResultFromTextFile(IEnumerable<int> src)
{
var filePath = @"C:\BoaSorte\Banco\testeResultado.txt";
var delimiter = new[] { ' ' };
var dict = new Dictionary<int, int>();
foreach (var line in File.ReadLines(filePath).Where(line => !string.IsNullOrEmpty(line)))
{
var values = line.Split(delimiter, StringSplitOptions.RemoveEmptyEntries)
.Select(x => int.Parse(x));
var matchCount = values.Count(v => src.Contains(v));
if (matchCount <= 15)
{
if (!dict.ContainsKey(matchCount))
{
dict[matchCount] = 0;
}
dict[matchCount]++;
}
}
return dict;
}
private void button1_Click(object sender, EventArgs e)
{
int outVal;
if (UltimoResultado.Any(Acertos => !int.TryParse(Acertos.Text, out outVal)))
{
MessageBox.Show("Valores Invalidos...");
return;
}
var arr = UltimoResultado.Select(linha => int.Parse(linha.Text));
var result = GetResultFromTextFile(arr).ToList();
for (int i = 0; i < result.Count; i++)
{
dgHits.Rows.Add();
dgHits.Rows[i].Cells["Acertos"].Value = result[i].Value.ToString();
}
}
|
|
|
|
|
Andre Oosthuizen wrote:
if (!dict.ContainsKey(matchCount))
{
dict[matchCount] = 0;
}
dict[matchCount]++; That checks whether the dictionary contains the key; sets the value if it doesn't; gets the value; then sets the value again.
It would be more efficient to use:
dict.TryGetValue(matchCount, out int existing);
dict[matchCount] = existing + 1; If the dictionary doesn't contain the key, the existing variable will be set to 0 .
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
André Oosthuizen, thank you very much for your attention, I will try to explain myself better,
I need to show how many hits are in each line, comparing with the numbers generated in the array,
EX: line 1 --- 10 hits,
line2 --- 8 hits,
row 3 --- 10 hits,
line 4 --- 11 hits,
line 5 --- 11 hits,
row 6 --- 7 hits.
the code I have, shows me the total lines with 10 hits,
the total lines with 11 hits,
the total rows with 7 hits, Just exemplifying
*that's not what I need.
what i need each line to have the number of hits at the end of the line itself.
I'll leave an image to try to understand.
Exemple image
modified 10-Aug-23 17:45pm.
|
|
|
|
|
I solved my problem as follows
string[] lines = File.ReadAllLines(@"C:\BoaSorte\Banco\testeResultado.txt");
string[] line, contents, result;
int count;
result = textBox1.Text.Split();
for (int i = 0; i < lines.Length; i++)
{
contents = lines[i].Split(' ');
count = contents.Intersect(result).Count();
line = new string[16];
for (int j = 0; j < 15; j++)
line[j] = contents[j];
line[15] = count.ToString();
dgHits.Rows.Add(line);
}
Thanks for the help of André Oosthuizen and Richard Deeming
|
|
|
|
|
Only a pleasure, glad you found the solution!
|
|
|
|
|
I've been tasked with reading & writing file to/from sharepoint. I've never even seen Sharepoint before.
I have a Windows app that will load files from Sharepoint, run some processing, and write the results back out to Sharepoint. They have made me an admin on it so I can set things up.
I've been Googling, but all I get are snippets with little context.
I'm going to ask some stupid questions...
- How do I setup the location(s) I need?
- Are there actual folders I can read/write from? How do I reference them? Like a drive letter? Or do I need an API?
- Where do I go to get sharted doing this with C#?
Thanks
In theory, theory and practice are the same. But in practice, they never are.”
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
|
|
|
|
|
I did some searching and I trust the following is what you might need going forward -
1) To set up your SharePoint Site, have a look at - MS Support | Create a site in SharePoint[^]
2) SharePoint uses different authentication methods, often involving OAuth tokens or username/password credentials. You'll need to confirm the authentication mechanism that your company uses. Common libraries for handling authentication include Microsoft's MSAL (Microsoft Authentication Library) or ADAL (Active Directory Authentication Library) for OAuth-based authentication. You will find more at - MS Support | With a Mismatch Error | Authentication settings in Central Administration do not match the configuration in web.config[^]
MS Learn | Overview of the Microsoft Authentication Library (MSAL)[^]
MS Azure | Active Directory Authentication Library (ADAL)[^]
3) SharePoint has REST APIs that allow you to interact with it programmatically. Alternatively, there are client libraries provided by Microsoft that can simplify the process of interacting with SharePoint using C#. The Microsoft Graph API is a newer unified API that can also be used to work with SharePoint. See more at - Lists vs. Libraries in SharePoint Online[^]
4) In SharePoint, you have libraries that act like folders. Documents are stored within these libraries.
You can access files using URLs like 'https://your_site.sharepoint.com/sites/your_site_name/your-library-name/your-file-path'.
With APIs, you'll use HTTP requests (GET, PUT, POST, DELETE) to interact with SharePoint. For C#, you can use libraries like HttpClient for making these requests. See more at - MS Support | Work with files in a document library[^]
As a high level example of how you might use 'HttpClient' to read a file from SharePoint using C# -
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
string url = "https://<your-domain>.sharepoint.com/sites/<site-name>/<library-name>/<file-path>";
string accessToken = "<your-access-token>";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
HttpResponseMessage response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
}
else
{
Console.WriteLine("Error: " + response.StatusCode);
}
}
}
}
Another example can be found at - How to read and write a text file from sharepoint[^]
|
|
|
|
|
That's awesome. Thank you
In theory, theory and practice are the same. But in practice, they never are.”
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
|
|
|
|
|
You're welcome. If you think it it helps you out, please give a like, thanks Kevin.
|
|
|
|
|
These changes make me wonder if using an abstract class doesn't already offer these facilities. Would you use them ? Don't these extensions contradict the "classic" model ? Your view ?Quote: 1. Default Implementations: As mentioned earlier, interfaces can now have default implementations of methods. This allows you to add new methods to your interfaces without breaking existing implementations.
2. Static and Instance Members: Interfaces can now contain static methods, instance methods, and operators.
3. Private and Protected Members: Interfaces can now contain private and protected members. This can be useful for providing helper methods used by the default implementations.
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
modified 6-Aug-23 10:09am.
|
|
|
|
|
These features may make sense because in a sense, they now support multiple inheritance in .NET.
If interfaces can have methods and instance members, and you can derive from multiple interfaces, then that would be a pretty close approximation of multiple inheritance.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Richard Andrew x64 wrote: a pretty close approximation of multiple inheritance. in a way abstract classes do not ?
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
There must be ways to use abstract classes that I never thought of.
I never saw it as a multiple-inheritance mechanism. But I am a simple-minded soul.
|
|
|
|
|
You can't multi-inherit abstract classes, but in all versions you can inherit from a base class and multiple Interfaces.
So adding default methods to Interfaces brings them a lot closer to a class and a fair impersonation of multiple class inheritance - remember that the only real difference between a "traditional" Interface and an abstract class is that the interface contains no code but enforces what you must implement, while the class provides methods and requires implementation.
It's useful, but ... just like var and dynamic it's wide open to abuse, and going to give problems when you inherit "lazy coder" apps.
"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!
|
|
|
|
|